From 46067e7aa615e492db6c0f43bbcb0c064d88a688 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 17 Oct 2023 21:02:52 +0800 Subject: [PATCH] add file cache for ipldv2 --- share/eds/byzantine/share_proof.go | 6 +- share/eds/cache_file.go | 146 ++++++++++++++++++++++ share/eds/file.go | 30 +++-- share/eds/file_test.go | 160 ++++++++++++++++++++++++- share/eds/{ods_file.go => mem_file.go} | 23 +++- share/getters/getter_test.go | 93 ++++++++++++++ share/ipld/get.go | 4 +- share/ipld/nmt_adder.go | 25 +++- share/ipldv2/blockstore.go | 10 +- 9 files changed, 465 insertions(+), 32 deletions(-) create mode 100644 share/eds/cache_file.go rename share/eds/{ods_file.go => mem_file.go} (78%) diff --git a/share/eds/byzantine/share_proof.go b/share/eds/byzantine/share_proof.go index 98b58ebbec..8957b9adc5 100644 --- a/share/eds/byzantine/share_proof.go +++ b/share/eds/byzantine/share_proof.go @@ -23,7 +23,7 @@ type ShareWithProof struct { // Share is a full data including namespace share.Share // Proof is a Merkle Proof of current share - Proof *nmt.Proof + Proof nmt.Proof } // NewShareWithProof takes the given leaf and its path, starting from the tree root, @@ -38,7 +38,7 @@ func NewShareWithProof(index int, share share.Share, pathToLeaf []cid.Cid) *Shar proof := nmt.NewInclusionProof(index, index+1, rangeProofs, true) return &ShareWithProof{ share, - &proof, + proof, } } @@ -119,7 +119,7 @@ func ProtoToShare(protoShares []*pb.Share) []*ShareWithProof { continue } proof := ProtoToProof(share.Proof) - shares[i] = &ShareWithProof{share.Data, &proof} + shares[i] = &ShareWithProof{share.Data, proof} } return shares } diff --git a/share/eds/cache_file.go b/share/eds/cache_file.go new file mode 100644 index 0000000000..7c7fe659b8 --- /dev/null +++ b/share/eds/cache_file.go @@ -0,0 +1,146 @@ +package eds + +import ( + "context" + "errors" + "fmt" + + "github.com/ipfs/boxo/blockservice" + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + + "github.com/celestiaorg/celestia-app/pkg/wrapper" + "github.com/celestiaorg/nmt" + "github.com/celestiaorg/rsmt2d" + + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine" + "github.com/celestiaorg/celestia-node/share/ipld" +) + +type CacheFile struct { + File + + // TODO(@walldiss): add columns support + rowCache map[int]inMemoryAxis + // disableCache disables caching of rows for testing purposes + disableCache bool +} + +type inMemoryAxis struct { + shares []share.Share + proofs blockservice.BlockGetter +} + +func NewCacheFile(f File) *CacheFile { + return &CacheFile{ + File: f, + rowCache: make(map[int]inMemoryAxis), + } +} + +func (f *CacheFile) ShareWithProof( + ctx context.Context, + idx int, + axis rsmt2d.Axis, + axisRoot []byte, +) (*byzantine.ShareWithProof, error) { + sqrLn := f.Size() + axsIdx, shrIdx := idx/sqrLn, idx%sqrLn + if axis == rsmt2d.Col { + axsIdx, shrIdx = shrIdx, axsIdx + } + + row := f.rowCache[axsIdx] + if row.proofs == nil { + shrs, err := f.Axis(axsIdx, axis) + if err != nil { + return nil, err + } + + // calculate proofs + adder := ipld.NewProofsAdder(sqrLn*2, ipld.CollectShares) + tree := wrapper.NewErasuredNamespacedMerkleTree(uint64(sqrLn/2), uint(axsIdx), + nmt.NodeVisitor(adder.VisitFn())) + for _, shr := range shrs { + err = tree.Push(shr) + if err != nil { + return nil, err + } + } + + if _, err := tree.Root(); err != nil { + return nil, err + } + + row = inMemoryAxis{ + shares: shrs, + proofs: newRowProofsGetter(adder.Proofs()), + } + + if !f.disableCache { + f.rowCache[axsIdx] = row + } + } + + // TODO(@walldiss): find prealloc size for proofs + proof := make([]cid.Cid, 0, 8) + rootCid := ipld.MustCidFromNamespacedSha256(axisRoot) + proofs, err := ipld.GetProof(ctx, row.proofs, rootCid, proof, shrIdx, sqrLn) + if err != nil { + return nil, fmt.Errorf("bulding proof from cache: %w", err) + } + + return byzantine.NewShareWithProof(shrIdx, row.shares[shrIdx], proofs), nil +} + +func (f *CacheFile) Axis(idx int, axis rsmt2d.Axis) ([]share.Share, error) { + row, ok := f.rowCache[idx] + if ok { + return row.shares, nil + } + + shrs, err := f.File.Axis(idx, axis) + if err != nil { + return nil, err + } + + // cache row shares + if !f.disableCache { + f.rowCache[idx] = inMemoryAxis{ + shares: shrs, + } + } + return shrs, nil +} + +// TODO(@walldiss): needs to be implemented +func (f *CacheFile) EDS() (*rsmt2d.ExtendedDataSquare, error) { + return f.File.EDS() +} + +// rowProofsGetter implements blockservice.BlockGetter interface +type rowProofsGetter struct { + proofs map[cid.Cid]blocks.Block +} + +func newRowProofsGetter(rawProofs map[cid.Cid][]byte) *rowProofsGetter { + proofs := make(map[cid.Cid]blocks.Block, len(rawProofs)) + for k, v := range rawProofs { + proofs[k] = blocks.NewBlock(v) + } + return &rowProofsGetter{ + proofs: proofs, + } +} + +func (r rowProofsGetter) GetBlock(_ context.Context, c cid.Cid) (blocks.Block, error) { + if b, ok := r.proofs[c]; ok { + return b, nil + } + return nil, errors.New("block not found") +} + +func (r rowProofsGetter) GetBlocks(_ context.Context, _ []cid.Cid) <-chan blocks.Block { + panic("not implemented") +} diff --git a/share/eds/file.go b/share/eds/file.go index f353b13002..2a34fae6c9 100644 --- a/share/eds/file.go +++ b/share/eds/file.go @@ -1,6 +1,7 @@ package eds import ( + "context" "fmt" "io" "os" @@ -8,16 +9,23 @@ import ( "golang.org/x/exp/mmap" "github.com/celestiaorg/celestia-app/pkg/wrapper" - "github.com/celestiaorg/nmt" "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine" ) +// TODO(@walldiss): Add context to all operations, so it don't backfire later type File interface { io.Closer Size() int - ShareWithProof(idx int, axis rsmt2d.Axis) (share.Share, nmt.Proof, error) + ShareWithProof( + ctx context.Context, + idx int, + axis rsmt2d.Axis, + axisRoot []byte, + // TODO(@walldiss): move ShareWithProof to share pkg + ) (*byzantine.ShareWithProof, error) Axis(idx int, axis rsmt2d.Axis) ([]share.Share, error) AxisHalf(idx int, axis rsmt2d.Axis) ([]share.Share, error) EDS() (*rsmt2d.ExtendedDataSquare, error) @@ -179,7 +187,12 @@ func (f *LazyFile) AxisHalf(idx int, axis rsmt2d.Axis) ([]share.Share, error) { return fullAxis[:len(fullAxis)/2], nil } -func (f *LazyFile) ShareWithProof(idx int, axis rsmt2d.Axis) (share.Share, nmt.Proof, error) { +func (f *LazyFile) ShareWithProof( + _ context.Context, + idx int, + axis rsmt2d.Axis, + _ []byte, +) (*byzantine.ShareWithProof, error) { // TODO: Cache the axis as well as computed tree sqrLn := int(f.hdr.squareSize) axsIdx, shrIdx := idx/sqrLn, idx%sqrLn @@ -189,23 +202,26 @@ func (f *LazyFile) ShareWithProof(idx int, axis rsmt2d.Axis) (share.Share, nmt.P shrs, err := f.Axis(axsIdx, axis) if err != nil { - return nil, nmt.Proof{}, err + return nil, err } tree := wrapper.NewErasuredNamespacedMerkleTree(uint64(sqrLn/2), uint(axsIdx)) for _, shr := range shrs { err = tree.Push(shr) if err != nil { - return nil, nmt.Proof{}, err + return nil, err } } proof, err := tree.ProveRange(shrIdx, shrIdx+1) if err != nil { - return nil, nmt.Proof{}, err + return nil, err } - return shrs[shrIdx], proof, nil + return &byzantine.ShareWithProof{ + Share: shrs[shrIdx], + Proof: proof, + }, nil } func (f *LazyFile) EDS() (*rsmt2d.ExtendedDataSquare, error) { diff --git a/share/eds/file_test.go b/share/eds/file_test.go index 53e1bad8c8..823b7a547b 100644 --- a/share/eds/file_test.go +++ b/share/eds/file_test.go @@ -1,7 +1,11 @@ package eds import ( + "context" "crypto/sha256" + "fmt" + "runtime" + "strconv" "testing" "github.com/stretchr/testify/assert" @@ -54,13 +58,13 @@ func TestFile(t *testing.T) { for _, axis := range axis { for i := 0; i < width*width; i++ { row, col := uint(i/width), uint(i%width) - shr, prf, err := fl.ShareWithProof(i, axis) + shr, err := fl.ShareWithProof(context.TODO(), i, axis, nil) require.NoError(t, err) assert.EqualValues(t, eds.GetCell(row, col), shr) namespace := share.ParitySharesNamespace if int(row) < width/2 && int(col) < width/2 { - namespace = share.GetNamespace(shr) + namespace = share.GetNamespace(shr.Share) } axishash := root.RowRoots[row] @@ -68,7 +72,7 @@ func TestFile(t *testing.T) { axishash = root.ColumnRoots[col] } - ok := prf.VerifyInclusion(sha256.New(), namespace.ToNMT(), [][]byte{shr}, axishash) + ok := shr.Proof.VerifyInclusion(sha256.New(), namespace.ToNMT(), [][]byte{shr.Share}, axishash) assert.True(t, ok) } } @@ -80,3 +84,153 @@ func TestFile(t *testing.T) { err = fl.Close() require.NoError(t, err) } + +// BenchmarkGetShareFromDisk/16 32978 35484 ns/op +// BenchmarkGetShareFromDisk/32 17452 68491 ns/op +// BenchmarkGetShareFromDisk/64 8184 131113 ns/op +// BenchmarkGetShareFromDisk/128 4574 265150 ns/op +func BenchmarkGetShareFromDisk(b *testing.B) { + minSize, maxSize := 16, 128 + dir := b.TempDir() + newFile := func(size int) File { + sqr := edstest.RandEDS(b, size) + f, err := CreateFile(dir+"/"+strconv.Itoa(size), sqr) + require.NoError(b, err) + return f + } + + benchGetShareFromFile(b, newFile, minSize, maxSize) +} + +// BenchmarkGetShareFromMem/16 30717 35675 ns/op +// BenchmarkGetShareFromMem/32 17617 69203 ns/op +// BenchmarkGetShareFromMem/64 7988 134039 ns/op +// BenchmarkGetShareFromMem/128 4582 264621 ns/op +func BenchmarkGetShareFromMem(b *testing.B) { + minSize, maxSize := 16, 128 + newFile := func(size int) File { + sqr := edstest.RandEDS(b, size) + return &MemFile{Eds: sqr} + } + + benchGetShareFromFile(b, newFile, minSize, maxSize) +} + +// BenchmarkGetShareFromCache/16 655171 1723 ns/op +// BenchmarkGetShareFromCache/32 568992 1998 ns/op +// BenchmarkGetShareFromCache/64 530446 2252 ns/op +// BenchmarkGetShareFromCache/128 519739 2515 ns/op +func BenchmarkGetShareFromCache(b *testing.B) { + minSize, maxSize := 16, 128 + newFile := func(size int) File { + sqr := edstest.RandEDS(b, size) + return NewCacheFile(&MemFile{Eds: sqr}) + } + + benchGetShareFromFile(b, newFile, minSize, maxSize) +} + +// BenchmarkGetShareFromCacheMiss/16 16308 72295 ns/op +// BenchmarkGetShareFromCacheMiss/32 8216 141334 ns/op +// BenchmarkGetShareFromCacheMiss/64 3877 284171 ns/op +// BenchmarkGetShareFromCacheMiss/128 2146 552244 ns/op +func BenchmarkGetShareFromCacheMiss(b *testing.B) { + minSize, maxSize := 16, 128 + newFile := func(size int) File { + sqr := edstest.RandEDS(b, size) + f := NewCacheFile(&MemFile{Eds: sqr}) + f.disableCache = true + return f + } + + benchGetShareFromFile(b, newFile, minSize, maxSize) +} + +func TestCacheMemoryUsageMany(t *testing.T) { + for i := 0; i < 10; i++ { + TestCacheMemoryUsage(t) + } +} + +// Allocations in kB +// Mem size before: 370802 +// Mem size after: 982305 +// Diff between snapshots: +// Alloc size: 611502 TotalAlloc (without GC): 1544656 Heap size: 611502 +func TestCacheMemoryUsage(t *testing.T) { + size := 128 + amount := 10 + dir := t.TempDir() + + type test struct { + file File + rows [][]byte + } + tests := make([]test, amount) + for i := range tests { + eds := edstest.RandEDS(t, size) + df, err := CreateFile(dir+"/"+strconv.Itoa(i), eds) + require.NoError(t, err) + f := NewCacheFile(df) + + rows, err := eds.RowRoots() + require.NoError(t, err) + tests[i] = test{ + file: f, + rows: rows, + } + } + + for sample := 0; sample < 2; sample++ { + var m1, m2 runtime.MemStats + runtime.GC() + runtime.ReadMemStats(&m1) + + for _, test := range tests { + for i := 0; i < size; i++ { + _, err := test.file.ShareWithProof(context.TODO(), 2*i*size, rsmt2d.Row, test.rows[i]) + require.NoError(t, err) + } + } + + runtime.GC() + runtime.ReadMemStats(&m2) + memUsage(&m1, &m2) + } +} + +func memUsage(m1, m2 *runtime.MemStats) { + fmt.Println("Mem size before:", (m1.Alloc)/1024) + + fmt.Println("Mem size after:", (m2.Alloc)/1024) + + fmt.Println("Diff between snapshots:\n", + "Alloc size:", (int(m2.Alloc)-int(m1.Alloc))/1024, + "TotalAlloc (without GC):", (int(m2.TotalAlloc)-int(m1.TotalAlloc))/1024, + "Heap size:", (int(m2.HeapAlloc)-int(m1.HeapAlloc))/1024, + ) +} + +func benchGetShareFromFile(b *testing.B, newFile func(size int) File, minSize, maxSize int) { + for size := minSize; size <= maxSize; size *= 2 { + name := strconv.Itoa(size) + b.Run(name, func(b *testing.B) { + f := newFile(size) + + sqr, err := f.EDS() + require.NoError(b, err) + roots, err := sqr.RowRoots() + require.NoError(b, err) + + // warm up cache + _, err = f.ShareWithProof(context.TODO(), 0, rsmt2d.Row, roots[0]) + require.NoError(b, err) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err = f.ShareWithProof(context.TODO(), 0, rsmt2d.Row, roots[0]) + require.NoError(b, err) + } + }) + } +} diff --git a/share/eds/ods_file.go b/share/eds/mem_file.go similarity index 78% rename from share/eds/ods_file.go rename to share/eds/mem_file.go index 6930174cc1..e368173e21 100644 --- a/share/eds/ods_file.go +++ b/share/eds/mem_file.go @@ -1,11 +1,13 @@ package eds import ( + "context" + "github.com/celestiaorg/celestia-app/pkg/wrapper" - "github.com/celestiaorg/nmt" "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine" ) type MemFile struct { @@ -20,7 +22,13 @@ func (f *MemFile) Size() int { return int(f.Eds.Width()) } -func (f *MemFile) ShareWithProof(idx int, axis rsmt2d.Axis) (share.Share, nmt.Proof, error) { +func (f *MemFile) ShareWithProof( + _ context.Context, + idx int, + axis rsmt2d.Axis, + _ []byte, + // TODO: move ShareWithProof to share pkg +) (*byzantine.ShareWithProof, error) { sqrLn := f.Size() axsIdx, shrIdx := idx/sqrLn, idx%sqrLn if axis == rsmt2d.Col { @@ -29,7 +37,7 @@ func (f *MemFile) ShareWithProof(idx int, axis rsmt2d.Axis) (share.Share, nmt.Pr shrs, err := f.Axis(axsIdx, axis) if err != nil { - return nil, nmt.Proof{}, err + return nil, err } // TODO(@Wondartan): this must access cached NMT on EDS instead of computing a new one @@ -37,16 +45,19 @@ func (f *MemFile) ShareWithProof(idx int, axis rsmt2d.Axis) (share.Share, nmt.Pr for _, shr := range shrs { err = tree.Push(shr) if err != nil { - return nil, nmt.Proof{}, err + return nil, err } } proof, err := tree.ProveRange(shrIdx, shrIdx+1) if err != nil { - return nil, nmt.Proof{}, err + return nil, err } - return shrs[shrIdx], proof, nil + return &byzantine.ShareWithProof{ + Share: shrs[shrIdx], + Proof: proof, + }, nil } func (f *MemFile) Axis(idx int, axis rsmt2d.Axis) ([]share.Share, error) { diff --git a/share/getters/getter_test.go b/share/getters/getter_test.go index bacb0a2c39..d798845b2b 100644 --- a/share/getters/getter_test.go +++ b/share/getters/getter_test.go @@ -7,12 +7,15 @@ import ( "time" "github.com/ipfs/boxo/exchange/offline" + "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" ds_sync "github.com/ipfs/go-datastore/sync" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/celestiaorg/celestia-app/pkg/da" "github.com/celestiaorg/celestia-app/pkg/wrapper" + dsbadger "github.com/celestiaorg/go-ds-badger4" "github.com/celestiaorg/rsmt2d" "github.com/celestiaorg/celestia-node/share" @@ -217,6 +220,96 @@ func TestIPLDGetter(t *testing.T) { }) } +// BenchmarkCacheHit/128 292264 3596 ns/op +func BenchmarkCacheHit(b *testing.B) { + size := 128 + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + b.Cleanup(cancel) + + // create store + dir := b.TempDir() + ds, err := dsbadger.NewDatastore(dir, &dsbadger.DefaultOptions) + require.NoError(b, err) + edsStore, err := eds.NewStore(eds.DefaultParameters(), dir, ds) + require.NoError(b, err) + err = edsStore.Start(ctx) + require.NoError(b, err) + + // generate EDS + edss := edstest.RandEDS(b, size) + dah, err := da.NewDataAvailabilityHeader(edss) + require.NoError(b, err) + err = edsStore.Put(ctx, dah.Hash(), edss) + require.NoError(b, err) + cid := ipld.MustCidFromNamespacedSha256(dah.RowRoots[0]) + + bstore := edsStore.Blockstore() + + // start benchmark + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := bstore.Get(ctx, cid) + require.NoError(b, err) + } +} + +// BenchmarkCacheEviction benchmarks the time it takes to load a block to the cache, when the +// cache size is set to 1. This forces cache eviction on every read. +// BenchmarkCacheEviction/128 254 4168392 ns/op +func BenchmarkCacheEviction(b *testing.B) { + const ( + blocks = 10 + size = 128 + ) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + b.Cleanup(cancel) + + dir := b.TempDir() + ds, err := dsbadger.NewDatastore(dir, &dsbadger.DefaultOptions) + require.NoError(b, err) + + newStore := func(params *eds.Parameters) *eds.Store { + edsStore, err := eds.NewStore(params, dir, ds) + require.NoError(b, err) + err = edsStore.Start(ctx) + require.NoError(b, err) + return edsStore + } + edsStore := newStore(eds.DefaultParameters()) + + // generate EDSs and store them + cids := make([]cid.Cid, blocks) + for i := range cids { + eds := edstest.RandEDS(b, size) + dah, err := da.NewDataAvailabilityHeader(eds) + require.NoError(b, err) + err = edsStore.Put(ctx, dah.Hash(), eds) + require.NoError(b, err) + + // store cids for read loop later + cids[i] = ipld.MustCidFromNamespacedSha256(dah.RowRoots[0]) + } + + // restart store to clear cache + require.NoError(b, edsStore.Stop(ctx)) + + // set BlockstoreCacheSize to 1 to force eviction on every read + params := eds.DefaultParameters() + params.BlockstoreCacheSize = 1 + bstore := newStore(params).Blockstore() + + // start benchmark + b.ResetTimer() + for i := 0; i < b.N; i++ { + h := cids[i%blocks] + // every read will trigger eviction + _, err := bstore.Get(ctx, h) + require.NoError(b, err) + } +} + func randomEDS(t *testing.T) (*rsmt2d.ExtendedDataSquare, *share.Root) { eds := edstest.RandEDS(t, 4) dah, err := share.NewRoot(eds) diff --git a/share/ipld/get.go b/share/ipld/get.go index f263877dc0..88a8e05b68 100644 --- a/share/ipld/get.go +++ b/share/ipld/get.go @@ -189,9 +189,7 @@ func GetProof( // look for links lnks := nd.Links() if len(lnks) == 0 { - p := make([]cid.Cid, len(proof)) - copy(p, proof) - return p, nil + return proof, nil } // route walk to appropriate children diff --git a/share/ipld/nmt_adder.go b/share/ipld/nmt_adder.go index 7ce52859b2..9f60e8e785 100644 --- a/share/ipld/nmt_adder.go +++ b/share/ipld/nmt_adder.go @@ -103,16 +103,27 @@ func BatchSize(squareSize int) int { // ProofsAdder is used to collect proof nodes, while traversing merkle tree type ProofsAdder struct { - lock sync.RWMutex - proofs map[cid.Cid][]byte + lock sync.RWMutex + proofs map[cid.Cid][]byte + addShares bool +} + +type AdderOption func(p *ProofsAdder) + +func CollectShares(p *ProofsAdder) { + p.addShares = true } // NewProofsAdder creates new instance of ProofsAdder. -func NewProofsAdder(squareSize int) *ProofsAdder { - return &ProofsAdder{ +func NewProofsAdder(squareSize int, opts ...AdderOption) *ProofsAdder { + p := &ProofsAdder{ // preallocate map to fit all inner nodes for given square size proofs: make(map[cid.Cid][]byte, innerNodesAmount(squareSize)), } + for _, o := range opts { + o(p) + } + return p } // CtxWithProofsAdder creates context, that will contain ProofsAdder. If context is leaked to @@ -174,7 +185,11 @@ func (a *ProofsAdder) Purge() { func (a *ProofsAdder) visitInnerNodes(hash []byte, children ...[]byte) { switch len(children) { case 1: - break + if !a.addShares { + break + } + id := MustCidFromNamespacedSha256(hash) + a.addProof(id, children[0]) case 2: id := MustCidFromNamespacedSha256(hash) a.addProof(id, append(children[0], children[1]...)) diff --git a/share/ipldv2/blockstore.go b/share/ipldv2/blockstore.go index 6ac55b358b..ee91f371c5 100644 --- a/share/ipldv2/blockstore.go +++ b/share/ipldv2/blockstore.go @@ -26,7 +26,7 @@ func NewBlockstore[F eds.File](fs fileStore[F]) blockstore.Blockstore { return &Blockstore[F]{fs} } -func (b Blockstore[F]) Get(_ context.Context, cid cid.Cid) (blocks.Block, error) { +func (b Blockstore[F]) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { switch cid.Type() { case shareSamplingCodec: id, err := ShareSampleIDFromCID(cid) @@ -36,7 +36,7 @@ func (b Blockstore[F]) Get(_ context.Context, cid cid.Cid) (blocks.Block, error) return nil, err } - blk, err := b.getShareSampleBlock(id) + blk, err := b.getShareSampleBlock(ctx, id) if err != nil { log.Error(err) return nil, err @@ -63,18 +63,18 @@ func (b Blockstore[F]) Get(_ context.Context, cid cid.Cid) (blocks.Block, error) } } -func (b Blockstore[F]) getShareSampleBlock(id ShareSampleID) (blocks.Block, error) { +func (b Blockstore[F]) getShareSampleBlock(ctx context.Context, id ShareSampleID) (blocks.Block, error) { f, err := b.fs.File(id.DataHash) if err != nil { return nil, fmt.Errorf("while getting EDS file from FS: %w", err) } - shr, prf, err := f.ShareWithProof(id.Index, id.Axis) + shr, err := f.ShareWithProof(ctx, id.Index, id.Axis, id.AxisHash) if err != nil { return nil, fmt.Errorf("while getting share with proof: %w", err) } - s := NewShareSample(id, shr, prf, f.Size()) + s := NewShareSample(id, shr.Share, shr.Proof, f.Size()) blk, err := s.IPLDBlock() if err != nil { return nil, fmt.Errorf("while coverting to IPLD block: %w", err)