github.com/sunrise-zone/sunrise-node@v0.13.1-sr2/share/getters/store.go (about)

     1  package getters
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"go.opentelemetry.io/otel/attribute"
     9  	"go.opentelemetry.io/otel/trace"
    10  
    11  	"github.com/celestiaorg/rsmt2d"
    12  
    13  	"github.com/sunrise-zone/sunrise-node/header"
    14  	"github.com/sunrise-zone/sunrise-node/libs/utils"
    15  	"github.com/sunrise-zone/sunrise-node/share"
    16  	"github.com/sunrise-zone/sunrise-node/share/eds"
    17  	"github.com/sunrise-zone/sunrise-node/share/ipld"
    18  )
    19  
    20  var _ share.Getter = (*StoreGetter)(nil)
    21  
    22  // StoreGetter is a share.Getter that retrieves shares from an eds.Store. No results are saved to
    23  // the eds.Store after retrieval.
    24  type StoreGetter struct {
    25  	store *eds.Store
    26  }
    27  
    28  // NewStoreGetter creates a new share.Getter that retrieves shares from an eds.Store.
    29  func NewStoreGetter(store *eds.Store) *StoreGetter {
    30  	return &StoreGetter{
    31  		store: store,
    32  	}
    33  }
    34  
    35  // GetShare gets a single share at the given EDS coordinates from the eds.Store through the
    36  // corresponding CAR-level blockstore.
    37  func (sg *StoreGetter) GetShare(ctx context.Context, header *header.ExtendedHeader, row, col int) (share.Share, error) {
    38  	dah := header.DAH
    39  	var err error
    40  	ctx, span := tracer.Start(ctx, "store/get-share", trace.WithAttributes(
    41  		attribute.Int("row", row),
    42  		attribute.Int("col", col),
    43  	))
    44  	defer func() {
    45  		utils.SetStatusAndEnd(span, err)
    46  	}()
    47  
    48  	upperBound := len(dah.RowRoots)
    49  	if row >= upperBound || col >= upperBound {
    50  		err := share.ErrOutOfBounds
    51  		span.RecordError(err)
    52  		return nil, err
    53  	}
    54  	root, leaf := ipld.Translate(dah, row, col)
    55  	bs, err := sg.store.CARBlockstore(ctx, dah.Hash())
    56  	if errors.Is(err, eds.ErrNotFound) {
    57  		// convert error to satisfy getter interface contract
    58  		err = share.ErrNotFound
    59  	}
    60  	if err != nil {
    61  		return nil, fmt.Errorf("getter/store: failed to retrieve blockstore: %w", err)
    62  	}
    63  	defer func() {
    64  		if err := bs.Close(); err != nil {
    65  			log.Warnw("closing blockstore", "err", err)
    66  		}
    67  	}()
    68  
    69  	// wrap the read-only CAR blockstore in a getter
    70  	blockGetter := eds.NewBlockGetter(bs)
    71  	s, err := ipld.GetShare(ctx, blockGetter, root, leaf, len(dah.RowRoots))
    72  	if errors.Is(err, ipld.ErrNodeNotFound) {
    73  		// convert error to satisfy getter interface contract
    74  		err = share.ErrNotFound
    75  	}
    76  	if err != nil {
    77  		return nil, fmt.Errorf("getter/store: failed to retrieve share: %w", err)
    78  	}
    79  
    80  	return s, nil
    81  }
    82  
    83  // GetEDS gets the EDS identified by the given root from the EDS store.
    84  func (sg *StoreGetter) GetEDS(
    85  	ctx context.Context, header *header.ExtendedHeader,
    86  ) (data *rsmt2d.ExtendedDataSquare, err error) {
    87  	ctx, span := tracer.Start(ctx, "store/get-eds")
    88  	defer func() {
    89  		utils.SetStatusAndEnd(span, err)
    90  	}()
    91  
    92  	data, err = sg.store.Get(ctx, header.DAH.Hash())
    93  	if errors.Is(err, eds.ErrNotFound) {
    94  		// convert error to satisfy getter interface contract
    95  		err = share.ErrNotFound
    96  	}
    97  	if err != nil {
    98  		return nil, fmt.Errorf("getter/store: failed to retrieve eds: %w", err)
    99  	}
   100  	return data, nil
   101  }
   102  
   103  // GetSharesByNamespace gets all EDS shares in the given namespace from the EDS store through the
   104  // corresponding CAR-level blockstore.
   105  func (sg *StoreGetter) GetSharesByNamespace(
   106  	ctx context.Context,
   107  	header *header.ExtendedHeader,
   108  	namespace share.Namespace,
   109  ) (shares share.NamespacedShares, err error) {
   110  	ctx, span := tracer.Start(ctx, "store/get-shares-by-namespace", trace.WithAttributes(
   111  		attribute.String("namespace", namespace.String()),
   112  	))
   113  	defer func() {
   114  		utils.SetStatusAndEnd(span, err)
   115  	}()
   116  
   117  	ns, err := eds.RetrieveNamespaceFromStore(ctx, sg.store, header.DAH, namespace)
   118  	if err != nil {
   119  		return nil, fmt.Errorf("getter/store: %w", err)
   120  	}
   121  	return ns, nil
   122  }