@@ -261,3 +261,84 @@ func TestRefConsistencyProof(t *testing.T) {
261261 })
262262 }
263263}
264+
265+ func TestRefSubtreeConsistencyProof (t * testing.T ) {
266+ entries := LeafInputs ()
267+ hasher := rfc6962 .DefaultHasher
268+ fullRoot8 := refRootHash (entries [:8 ], hasher )
269+
270+ for _ , tc := range []struct {
271+ start uint64
272+ end uint64
273+ size uint64
274+ known bool
275+ want [][]byte
276+ }{
277+ // Empty subtrees (start == end) always return nil (empty proof).
278+ {start : 0 , end : 0 , size : 8 , known : true , want : nil },
279+ {start : 4 , end : 4 , size : 8 , known : true , want : nil },
280+ {start : 8 , end : 8 , size : 8 , known : true , want : nil },
281+ // Invalid ranges return nil.
282+ {start : 5 , end : 3 , size : 8 , known : true , want : nil },
283+ {start : 0 , end : 10 , size : 8 , known : true , want : nil },
284+ // Full tree [0, 8) in size 8.
285+ {start : 0 , end : 8 , size : 8 , known : true , want : nil },
286+ {start : 0 , end : 8 , size : 8 , known : false , want : [][]byte {fullRoot8 }},
287+ // Left half [0, 4) in size 8 requires the root of the right half [4, 8).
288+ {start : 0 , end : 4 , size : 8 , known : true , want : [][]byte {
289+ hd ("6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4" ),
290+ }},
291+ // Right half [4, 8) in size 8 requires the root of the left half [0, 4).
292+ {start : 4 , end : 8 , size : 8 , known : true , want : [][]byte {
293+ hd ("d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7" ),
294+ }},
295+ // Prefix subtree consistency cases matching TestRefConsistencyProof:
296+ {start : 0 , end : 1 , size : 1 , known : true , want : nil },
297+ {start : 0 , end : 1 , size : 8 , known : true , want : [][]byte {
298+ hd ("96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7" ),
299+ hd ("5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e" ),
300+ hd ("6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4" ),
301+ }},
302+ {start : 0 , end : 2 , size : 5 , known : true , want : [][]byte {
303+ hd ("5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e" ),
304+ hd ("bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b" ),
305+ }},
306+ {start : 0 , end : 6 , size : 8 , known : true , want : [][]byte {
307+ hd ("0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a" ),
308+ hd ("ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0" ),
309+ hd ("d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7" ),
310+ }},
311+ // Non-zero starting subtrees:
312+ // Subtree of size 1 not starting at 0 ([4, 5) in size 8):
313+ {start : 4 , end : 5 , size : 8 , known : true , want : [][]byte {
314+ hd ("4271a26be0d8a84f0bd54c8c302e7cb3a3b5d1fa6780a40bcce2873477dab658" ),
315+ hd ("ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0" ),
316+ hd ("d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7" ),
317+ }},
318+ // Subtree ending at size not starting at 0 ([6, 8) in size 8):
319+ {start : 6 , end : 8 , size : 8 , known : true , want : [][]byte {
320+ hd ("0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a" ),
321+ hd ("d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7" ),
322+ }},
323+ // Perfect subtree not starting at 0, not ending at size ([2, 4) in size 8):
324+ {start : 2 , end : 4 , size : 8 , known : true , want : [][]byte {
325+ hd ("fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125" ),
326+ hd ("6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4" ),
327+ }},
328+ // Imperfect subtree not starting at 0, not ending at size ([4, 7) in size 8):
329+ {start : 4 , end : 7 , size : 8 , known : true , want : [][]byte {
330+ hd ("b08693ec2e721597130641e8211e7eedccb4c26413963eee6c1e2ed16ffb1a5f" ),
331+ hd ("46f6ffadd3d06a09ff3c5860d2755c8b9819db7df44251788c7d8e3180de8eb1" ),
332+ hd ("0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a" ),
333+ hd ("d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7" ),
334+ }},
335+ } {
336+ t .Run (fmt .Sprintf ("start:%d end:%d size:%d known:%t" , tc .start , tc .end , tc .size , tc .known ), func (t * testing.T ) {
337+ got := refSubtreeConsistencyProof (tc .start , tc .end , entries [:tc .size ], tc .known , hasher )
338+ if diff := cmp .Diff (got , tc .want ); diff != "" {
339+ t .Errorf ("refSubtreeConsistencyProof: diff (-got +want)\n %s" , diff )
340+ }
341+ })
342+ }
343+ }
344+
0 commit comments