@@ -140,8 +140,8 @@ func RootFromConsistencyProof(hasher merkle.LogHasher, size1, size2 uint64, proo
140140}
141141
142142// RootFromSubtreeConsistencyProof calculates the expected root hash for a
143- // parent tree of the given size, from a subtree [start, end) with its root and
144- // a consistency proof.
143+ // parent tree of the given size, from a subtree [start, end) root and a
144+ // consistency proof.
145145//
146146// It requires:
147147// - 0 <= start < end <= size.
@@ -198,7 +198,13 @@ func rootFromSubtreeConsistencyProof(hasher merkle.LogHasher, start, end, size u
198198 // The proof starts at this level.
199199 shift := bits .TrailingZeros64 (end - start )
200200
201+ // The first node of the proof is the root of the rightmost subtree within
202+ // the argument subtree.
201203 seed , pStart := proof [0 ], 1
204+ // Unless the argument subtree is full, in which case that rightmost subtree
205+ // is the argument subtree itself. Its root is not included in the proof
206+ // since a client verifying a subtree inclusion proof is expected to already
207+ // know what the root of that subtree is.
202208 if (end - start ) == 1 << uint (shift ) {
203209 seed , pStart = subRoot , 0
204210 }
@@ -208,15 +214,24 @@ func rootFromSubtreeConsistencyProof(hasher merkle.LogHasher, start, end, size u
208214 }
209215 proof = proof [pStart :]
210216
217+ // Compute the root of the [start, end) subtree for trees of sizes
218+ // |end| and |size|.
211219 subtreeRoot , grownSubtreeRoot , remainingProof := chainSubtree (hasher , seed , proof , start , end , size )
212220 if err := verifyMatch (subtreeRoot , subRoot ); err != nil {
213221 return nil , err
214222 }
215223
216- h := bits .Len64 ((end - 1 ) ^ start )
217- macroIndex := start >> uint (h )
218- macroSize := ((size - 1 ) >> uint (h )) + 1
219- return RootFromInclusionProof (hasher , macroIndex , macroSize , grownSubtreeRoot , remainingProof )
224+ // The remainder of the proof is an inclusion proof for grownSubtreeRoot
225+ // into the parent tree of size |size|.
226+ // Shift the tree down for that node to be a leaf.
227+ // xor trims the common prefix between the first and last entry. The bit len
228+ // of the result is the height of the subtree.
229+ srHeight := bits .Len64 ((end - 1 ) ^ start )
230+ // shifting indexes to the srHeight times gives the size of the tree at level
231+ // srHeight.
232+ srIndex := start >> uint (srHeight )
233+ macroSize := ((size - 1 ) >> uint (srHeight )) + 1
234+ return RootFromInclusionProof (hasher , srIndex , macroSize , grownSubtreeRoot , remainingProof )
220235}
221236
222237// chainSubtree hashes nodes from proof up to subtree [start, end)'s root
0 commit comments