Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eds/store): store.GetDAH #1511

Merged
merged 12 commits into from
Dec 22, 2022
2 changes: 1 addition & 1 deletion share/eds/blockstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestBlockstore_Operations(t *testing.T) {
require.NoError(t, err)

topLevelBS := edsStore.Blockstore()
carBS, err := edsStore.CARBlockstore(ctx, dah.Hash())
carBS, _, err := edsStore.CARBlockstore(ctx, dah.Hash())
require.NoError(t, err)

blockstores := []dagstore.ReadBlockstore{topLevelBS, carBS}
Expand Down
39 changes: 34 additions & 5 deletions share/eds/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import (
"github.com/filecoin-project/dagstore/shard"
"github.com/ipfs/go-datastore"
bstore "github.com/ipfs/go-ipfs-blockstore"
carv1 "github.com/ipld/go-car"

"github.com/celestiaorg/rsmt2d"

"github.com/celestiaorg/celestia-node/header"
"github.com/celestiaorg/celestia-node/share"
"github.com/celestiaorg/celestia-node/share/ipld"
)

const (
Expand Down Expand Up @@ -197,16 +200,42 @@ func (s *Store) Blockstore() bstore.Blockstore {
return s.bs
}

// CARBlockstore returns the IPFS blockstore that provides access to the IPLD blocks stored in an
// individual CAR file.
func (s *Store) CARBlockstore(ctx context.Context, dataHash []byte) (dagstore.ReadBlockstore, error) {
// CARBlockstore returns the IPFS blockstore and DAH that provides access to the IPLD blocks stored
// in an individual CAR file.
func (s *Store) CARBlockstore(
ctx context.Context,
dataHash []byte,
) (dagstore.ReadBlockstore, *header.DataAvailabilityHeader, error) {
Wondertan marked this conversation as resolved.
Show resolved Hide resolved
key := shard.KeyFromString(fmt.Sprintf("%X", dataHash))
accessor, err := s.getAccessor(ctx, key)
if err != nil {
return nil, err
return nil, nil, fmt.Errorf("failed to get accessor: %w", err)
distractedm1nd marked this conversation as resolved.
Show resolved Hide resolved
}

return accessor.bs, nil
reader, err := carv1.NewCarReader(accessor.sa)
if err != nil {
return nil, nil, fmt.Errorf("failed to read DAH from car reader: %w", err)
distractedm1nd marked this conversation as resolved.
Show resolved Hide resolved
}
dah := dahFromCARHeader(reader.Header)
err = accessor.sa.Close()
if err != nil {
return nil, nil, fmt.Errorf("failed to close car reader after DAH retrieval: %w", err)
distractedm1nd marked this conversation as resolved.
Show resolved Hide resolved
distractedm1nd marked this conversation as resolved.
Show resolved Hide resolved
}

return accessor.bs, dah, nil
}

// dahFromCARHeader returns the DataAvailabilityHeader stored in the CIDs of a CARv1 header.
func dahFromCARHeader(carHeader *carv1.CarHeader) *header.DataAvailabilityHeader {
rootCount := len(carHeader.Roots)
rootBytes := make([][]byte, rootCount)
for i, root := range carHeader.Roots {
rootBytes[i] = ipld.NamespacedSha256FromCID(root)
}
walldiss marked this conversation as resolved.
Show resolved Hide resolved
return &header.DataAvailabilityHeader{
RowsRoots: rootBytes[:rootCount/2],
ColumnRoots: rootBytes[rootCount/2:],
}
}

func (s *Store) getAccessor(ctx context.Context, key shard.Key) (*accessorWithBlockstore, error) {
Expand Down
3 changes: 2 additions & 1 deletion share/eds/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,9 @@ func Test_BlockstoreCache(t *testing.T) {
assert.ErrorIs(t, err, errCacheMiss)

// now get it, so that the key is in the cache
_, err = edsStore.CARBlockstore(ctx, dah.Hash())
_, newDAH, err := edsStore.CARBlockstore(ctx, dah.Hash())
assert.NoError(t, err)
assert.True(t, dah.Equals(newDAH), "DAH integrity mismatch")
_, err = edsStore.cache.Get(shardKey)
assert.NoError(t, err, errCacheMiss)
}
Expand Down