github.com/sunrise-zone/sunrise-node@v0.13.1-sr2/share/eds/byzantine/share_proof.go (about)

     1  package byzantine
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  
     7  	"github.com/ipfs/boxo/blockservice"
     8  	"github.com/ipfs/go-cid"
     9  	logging "github.com/ipfs/go-log/v2"
    10  
    11  	"github.com/celestiaorg/nmt"
    12  	nmt_pb "github.com/celestiaorg/nmt/pb"
    13  
    14  	"github.com/sunrise-zone/sunrise-node/share"
    15  	pb "github.com/sunrise-zone/sunrise-node/share/eds/byzantine/pb"
    16  	"github.com/sunrise-zone/sunrise-node/share/ipld"
    17  )
    18  
    19  var log = logging.Logger("share/byzantine")
    20  
    21  // ShareWithProof contains data with corresponding Merkle Proof
    22  type ShareWithProof struct {
    23  	// Share is a full data including namespace
    24  	share.Share
    25  	// Proof is a Merkle Proof of current share
    26  	Proof *nmt.Proof
    27  }
    28  
    29  // NewShareWithProof takes the given leaf and its path, starting from the tree root,
    30  // and computes the nmt.Proof for it.
    31  func NewShareWithProof(index int, share share.Share, pathToLeaf []cid.Cid) *ShareWithProof {
    32  	rangeProofs := make([][]byte, 0, len(pathToLeaf))
    33  	for i := len(pathToLeaf) - 1; i >= 0; i-- {
    34  		node := ipld.NamespacedSha256FromCID(pathToLeaf[i])
    35  		rangeProofs = append(rangeProofs, node)
    36  	}
    37  
    38  	proof := nmt.NewInclusionProof(index, index+1, rangeProofs, true)
    39  	return &ShareWithProof{
    40  		share,
    41  		&proof,
    42  	}
    43  }
    44  
    45  // Validate validates inclusion of the share under the given root CID.
    46  func (s *ShareWithProof) Validate(root cid.Cid) bool {
    47  	return s.Proof.VerifyInclusion(
    48  		sha256.New(), // TODO(@Wondertan): This should be defined somewhere globally
    49  		share.GetNamespace(s.Share).ToNMT(),
    50  		[][]byte{share.GetData(s.Share)},
    51  		ipld.NamespacedSha256FromCID(root),
    52  	)
    53  }
    54  
    55  func (s *ShareWithProof) ShareWithProofToProto() *pb.Share {
    56  	if s == nil {
    57  		return &pb.Share{}
    58  	}
    59  
    60  	return &pb.Share{
    61  		Data: s.Share,
    62  		Proof: &nmt_pb.Proof{
    63  			Start:                 int64(s.Proof.Start()),
    64  			End:                   int64(s.Proof.End()),
    65  			Nodes:                 s.Proof.Nodes(),
    66  			LeafHash:              s.Proof.LeafHash(),
    67  			IsMaxNamespaceIgnored: s.Proof.IsMaxNamespaceIDIgnored(),
    68  		},
    69  	}
    70  }
    71  
    72  // GetProofsForShares fetches Merkle proofs for the given shares
    73  // and returns the result as an array of ShareWithProof.
    74  func GetProofsForShares(
    75  	ctx context.Context,
    76  	bGetter blockservice.BlockGetter,
    77  	root cid.Cid,
    78  	shares [][]byte,
    79  ) ([]*ShareWithProof, error) {
    80  	proofs := make([]*ShareWithProof, len(shares))
    81  	for index, share := range shares {
    82  		if share != nil {
    83  			proof, err := getProofsAt(ctx, bGetter, root, index, len(shares))
    84  			if err != nil {
    85  				return nil, err
    86  			}
    87  			proofs[index] = proof
    88  		}
    89  	}
    90  	return proofs, nil
    91  }
    92  
    93  func getProofsAt(
    94  	ctx context.Context,
    95  	bGetter blockservice.BlockGetter,
    96  	root cid.Cid,
    97  	index,
    98  	total int,
    99  ) (*ShareWithProof, error) {
   100  	proof := make([]cid.Cid, 0)
   101  	// TODO(@vgonkivs): Combine GetLeafData and GetProof in one function as the are traversing the same
   102  	// tree. Add options that will control what data will be fetched.
   103  	node, err := ipld.GetLeaf(ctx, bGetter, root, index, total)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	proof, err = ipld.GetProof(ctx, bGetter, root, proof, index, total)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	return NewShareWithProof(index, node.RawData(), proof), nil
   113  }
   114  
   115  func ProtoToShare(protoShares []*pb.Share) []*ShareWithProof {
   116  	shares := make([]*ShareWithProof, len(protoShares))
   117  	for i, share := range protoShares {
   118  		if share.Proof == nil {
   119  			continue
   120  		}
   121  		proof := ProtoToProof(share.Proof)
   122  		shares[i] = &ShareWithProof{share.Data, &proof}
   123  	}
   124  	return shares
   125  }
   126  
   127  func ProtoToProof(protoProof *nmt_pb.Proof) nmt.Proof {
   128  	return nmt.NewInclusionProof(
   129  		int(protoProof.Start),
   130  		int(protoProof.End),
   131  		protoProof.Nodes,
   132  		protoProof.IsMaxNamespaceIgnored,
   133  	)
   134  }