@@ -17,6 +17,7 @@ package client
17
17
import (
18
18
"bytes"
19
19
"context"
20
+ "crypto/sha256"
20
21
"errors"
21
22
"fmt"
22
23
"os"
@@ -25,6 +26,7 @@ import (
25
26
26
27
"github.com/transparency-dev/formats/log"
27
28
"github.com/transparency-dev/merkle/compact"
29
+ "github.com/transparency-dev/merkle/proof"
28
30
"github.com/transparency-dev/tessera/api"
29
31
"github.com/transparency-dev/tessera/api/layout"
30
32
"golang.org/x/mod/sumdb/note"
@@ -237,31 +239,46 @@ func TestHandleZeroRoot(t *testing.T) {
237
239
func TestGetEntryBundleAddressing (t * testing.T ) {
238
240
for _ , test := range []struct {
239
241
name string
240
- idx , logSize uint64
242
+ idx uint64
243
+ clientLogSize uint64
244
+ actualLogSize uint64
241
245
wantPartialTileSize uint8
242
246
}{
243
247
{
244
248
name : "works - partial tile" ,
245
249
idx : 0 ,
246
- logSize : 34 ,
250
+ clientLogSize : 34 ,
251
+ actualLogSize : 34 ,
247
252
wantPartialTileSize : 34 ,
248
253
},
249
254
{
250
255
name : "works - full tile" ,
251
256
idx : 1 ,
252
- logSize : layout .TileWidth * 2 + 45 ,
257
+ clientLogSize : layout .TileWidth * 2 + 45 ,
258
+ actualLogSize : layout .TileWidth * 2 + 45 ,
253
259
wantPartialTileSize : 0 ,
254
260
},
261
+ {
262
+ name : "works - request partial but fallback to full tile" ,
263
+ idx : 3 , // Request the partial bundle at the end of the log
264
+ clientLogSize : layout .TileWidth * 2 + 45 , // bundle 3 is partial according to client's PoV
265
+ actualLogSize : layout .TileWidth * 3 , // but the log has grown and bundle 3 is now full.
266
+ wantPartialTileSize : 0 , // so we expect the last call to the fetcher to be for a full bundle.
267
+ },
255
268
} {
256
269
t .Run (test .name , func (t * testing.T ) {
257
270
gotIdx := uint64 (0 )
258
271
gotTileSize := uint8 (0 )
259
272
f := func (_ context.Context , i uint64 , sz uint8 ) ([]byte , error ) {
260
273
gotIdx = i
261
274
gotTileSize = sz
275
+ p := layout .PartialTileSize (0 , i , test .actualLogSize )
276
+ if p != sz {
277
+ return nil , os .ErrNotExist
278
+ }
262
279
return []byte {}, nil
263
280
}
264
- _ , err := GetEntryBundle (context .Background (), f , test .idx , test .logSize )
281
+ _ , err := GetEntryBundle (context .Background (), f , test .idx , test .clientLogSize )
265
282
if err != nil {
266
283
t .Fatalf ("GetEntryBundle: %v" , err )
267
284
}
@@ -274,3 +291,76 @@ func TestGetEntryBundleAddressing(t *testing.T) {
274
291
})
275
292
}
276
293
}
294
+
295
+ func TestNodeFetcherAddressing (t * testing.T ) {
296
+ for _ , test := range []struct {
297
+ name string
298
+ nodeLevel uint
299
+ nodeIdx uint64
300
+ clientLogSize uint64
301
+ actualLogSize uint64
302
+ wantPartialTileSize uint8
303
+ }{
304
+ {
305
+ name : "works - partial tile" ,
306
+ nodeIdx : 0 ,
307
+ clientLogSize : 34 ,
308
+ actualLogSize : 34 ,
309
+ wantPartialTileSize : 34 ,
310
+ },
311
+ {
312
+ name : "works - full tile" ,
313
+ nodeIdx : 56 ,
314
+ clientLogSize : layout .TileWidth * 2 + 45 ,
315
+ actualLogSize : layout .TileWidth * 2 + 45 ,
316
+ wantPartialTileSize : 0 ,
317
+ },
318
+ {
319
+ name : "works - request partial but fallback to full tile" ,
320
+ nodeIdx : 3 * layout .TileWidth + 23 , // Request node from the partial tile at the end of the log
321
+ clientLogSize : layout .TileWidth * 2 + 45 , // tile 3 is partial according to client's PoV
322
+ actualLogSize : layout .TileWidth * 3 , // but the log has grown and tile 3 is now full.
323
+ wantPartialTileSize : 0 , // so we expect the last call to the fetcher to be for a full tile.
324
+ },
325
+ } {
326
+ t .Run (test .name , func (t * testing.T ) {
327
+ gotLevel , gotIdx , gotTileSize := uint (0 ), uint64 (0 ), uint8 (0 )
328
+ f := func (_ context.Context , l , i uint64 , sz uint8 ) ([]byte , error ) {
329
+ gotLevel = uint (l )
330
+ gotIdx = i
331
+ gotTileSize = sz
332
+ p := layout .PartialTileSize (l , i , test .actualLogSize )
333
+ if p != sz {
334
+ return nil , os .ErrNotExist
335
+ }
336
+ r := api.HashTile {}
337
+ s := int (sz )
338
+ if s == 0 {
339
+ s = layout .TileWidth
340
+ }
341
+ for x := range s {
342
+ h := sha256 .Sum256 (fmt .Appendf (nil , "node at %d/%d" , l , i + uint64 (x )))
343
+ r .Nodes = append (r .Nodes , h [:])
344
+ }
345
+ return r .MarshalText ()
346
+ }
347
+ pb , err := NewProofBuilder (t .Context (), test .clientLogSize , f )
348
+ if err != nil {
349
+ t .Fatalf ("NewProofBuilder: %v" , err )
350
+ }
351
+ _ , err = pb .fetchNodes (t .Context (), proof.Nodes {IDs : []compact.NodeID {compact .NewNodeID (test .nodeLevel , test .nodeIdx )}})
352
+ if err != nil {
353
+ t .Fatalf ("fetchNodes: %v" , err )
354
+ }
355
+ if wantLevel := test .nodeLevel >> layout .TileHeight ; gotLevel != wantLevel {
356
+ t .Errorf ("f got level %d, want %d" , gotLevel , wantLevel )
357
+ }
358
+ if wantIdx := test .nodeIdx >> layout .TileHeight ; gotIdx != wantIdx {
359
+ t .Errorf ("f got idx %d, want %d" , gotIdx , wantIdx )
360
+ }
361
+ if gotTileSize != test .wantPartialTileSize {
362
+ t .Errorf ("f got tileSize %d, want %d" , gotTileSize , test .wantPartialTileSize )
363
+ }
364
+ })
365
+ }
366
+ }
0 commit comments