github.com/celestiaorg/celestia-node@v0.15.0-beta.1/share/getter.go (about)

     1  package share
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"errors"
     7  	"fmt"
     8  
     9  	"github.com/celestiaorg/nmt"
    10  	"github.com/celestiaorg/rsmt2d"
    11  
    12  	"github.com/celestiaorg/celestia-node/header"
    13  )
    14  
    15  var (
    16  	// ErrNotFound is used to indicate that requested data could not be found.
    17  	ErrNotFound = errors.New("share: data not found")
    18  	// ErrOutOfBounds is used to indicate that a passed row or column index is out of bounds of the
    19  	// square size.
    20  	ErrOutOfBounds = errors.New("share: row or column index is larger than square size")
    21  )
    22  
    23  // Getter interface provides a set of accessors for shares by the Root.
    24  // Automatically verifies integrity of shares(exceptions possible depending on the implementation).
    25  //
    26  //go:generate mockgen -destination=mocks/getter.go -package=mocks . Getter
    27  type Getter interface {
    28  	// GetShare gets a Share by coordinates in EDS.
    29  	GetShare(ctx context.Context, header *header.ExtendedHeader, row, col int) (Share, error)
    30  
    31  	// GetEDS gets the full EDS identified by the given extended header.
    32  	GetEDS(context.Context, *header.ExtendedHeader) (*rsmt2d.ExtendedDataSquare, error)
    33  
    34  	// GetSharesByNamespace gets all shares from an EDS within the given namespace.
    35  	// Shares are returned in a row-by-row order if the namespace spans multiple rows.
    36  	// Inclusion of returned data could be verified using Verify method on NamespacedShares.
    37  	// If no shares are found for target namespace non-inclusion could be also verified by calling
    38  	// Verify method.
    39  	GetSharesByNamespace(context.Context, *header.ExtendedHeader, Namespace) (NamespacedShares, error)
    40  }
    41  
    42  // NamespacedShares represents all shares with proofs within a specific namespace of an EDS.
    43  type NamespacedShares []NamespacedRow
    44  
    45  // Flatten returns the concatenated slice of all NamespacedRow shares.
    46  func (ns NamespacedShares) Flatten() []Share {
    47  	shares := make([]Share, 0)
    48  	for _, row := range ns {
    49  		shares = append(shares, row.Shares...)
    50  	}
    51  	return shares
    52  }
    53  
    54  // NamespacedRow represents all shares with proofs within a specific namespace of a single EDS row.
    55  type NamespacedRow struct {
    56  	Shares []Share    `json:"shares"`
    57  	Proof  *nmt.Proof `json:"proof"`
    58  }
    59  
    60  // Verify validates NamespacedShares by checking every row with nmt inclusion proof.
    61  func (ns NamespacedShares) Verify(root *Root, namespace Namespace) error {
    62  	var originalRoots [][]byte
    63  	for _, row := range root.RowRoots {
    64  		if !namespace.IsOutsideRange(row, row) {
    65  			originalRoots = append(originalRoots, row)
    66  		}
    67  	}
    68  
    69  	if len(originalRoots) != len(ns) {
    70  		return fmt.Errorf("amount of rows differs between root and namespace shares: expected %d, got %d",
    71  			len(originalRoots), len(ns))
    72  	}
    73  
    74  	for i, row := range ns {
    75  		// verify row data against row hash from original root
    76  		if !row.verify(originalRoots[i], namespace) {
    77  			return fmt.Errorf("row verification failed: row %d doesn't match original root: %s", i, root.String())
    78  		}
    79  	}
    80  	return nil
    81  }
    82  
    83  // verify validates the row using nmt inclusion proof.
    84  func (row *NamespacedRow) verify(rowRoot []byte, namespace Namespace) bool {
    85  	// construct nmt leaves from shares by prepending namespace
    86  	leaves := make([][]byte, 0, len(row.Shares))
    87  	for _, shr := range row.Shares {
    88  		leaves = append(leaves, append(GetNamespace(shr), shr...))
    89  	}
    90  
    91  	// verify namespace
    92  	return row.Proof.VerifyNamespace(
    93  		sha256.New(),
    94  		namespace.ToNMT(),
    95  		leaves,
    96  		rowRoot,
    97  	)
    98  }