github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/snapshotgrpc/snapshot_service.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package snapshotgrpc
     8  
     9  import (
    10  	"context"
    11  	"time"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/golang/protobuf/ptypes/empty"
    15  	"github.com/hechain20/hechain/common/crypto"
    16  	"github.com/hechain20/hechain/core/aclmgmt/resources"
    17  	"github.com/hechain20/hechain/core/ledger"
    18  	"github.com/hechain20/hechain/protoutil"
    19  	cb "github.com/hyperledger/fabric-protos-go/common"
    20  	pb "github.com/hyperledger/fabric-protos-go/peer"
    21  	"github.com/pkg/errors"
    22  )
    23  
    24  // Snapshot Service implements SnapshotServer grpc interface
    25  type SnapshotService struct {
    26  	LedgerGetter LedgerGetter
    27  	ACLProvider  ACLProvider
    28  }
    29  
    30  // LedgerGetter gets the PeerLedger associated with a channel.
    31  type LedgerGetter interface {
    32  	GetLedger(cid string) ledger.PeerLedger
    33  }
    34  
    35  // ACLProvider checks ACL for a channelless resource
    36  type ACLProvider interface {
    37  	CheckACLNoChannel(resName string, idinfo interface{}) error
    38  }
    39  
    40  // Generate generates a snapshot request.
    41  func (s *SnapshotService) Generate(ctx context.Context, signedRequest *pb.SignedSnapshotRequest) (*empty.Empty, error) {
    42  	request := &pb.SnapshotRequest{}
    43  	if err := proto.Unmarshal(signedRequest.Request, request); err != nil {
    44  		return nil, errors.Wrap(err, "failed to unmarshal snapshot request")
    45  	}
    46  
    47  	if err := s.checkACL(resources.Snapshot_submitrequest, request.SignatureHeader, signedRequest); err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	lgr, err := s.getLedger(request.ChannelId)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	if err := lgr.SubmitSnapshotRequest(request.BlockNumber); err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	return &empty.Empty{}, nil
    61  }
    62  
    63  // Cancel cancels a snapshot request.
    64  func (s *SnapshotService) Cancel(ctx context.Context, signedRequest *pb.SignedSnapshotRequest) (*empty.Empty, error) {
    65  	request := &pb.SnapshotRequest{}
    66  	if err := proto.Unmarshal(signedRequest.Request, request); err != nil {
    67  		return nil, errors.Wrap(err, "failed to unmarshal snapshot request")
    68  	}
    69  
    70  	if err := s.checkACL(resources.Snapshot_cancelrequest, request.SignatureHeader, signedRequest); err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	lgr, err := s.getLedger(request.ChannelId)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	if err := lgr.CancelSnapshotRequest(request.BlockNumber); err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	return &empty.Empty{}, nil
    84  }
    85  
    86  // QueryPendings returns a list of pending snapshot requests.
    87  func (s *SnapshotService) QueryPendings(ctx context.Context, signedRequest *pb.SignedSnapshotRequest) (*pb.QueryPendingSnapshotsResponse, error) {
    88  	query := &pb.SnapshotQuery{}
    89  	if err := proto.Unmarshal(signedRequest.Request, query); err != nil {
    90  		return nil, errors.Wrap(err, "failed to unmarshal snapshot request")
    91  	}
    92  
    93  	if err := s.checkACL(resources.Snapshot_listpending, query.SignatureHeader, signedRequest); err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	lgr, err := s.getLedger(query.ChannelId)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	result, err := lgr.PendingSnapshotRequests()
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	return &pb.QueryPendingSnapshotsResponse{BlockNumbers: result}, nil
   108  }
   109  
   110  func (s *SnapshotService) checkACL(resName string, signatureHdr *cb.SignatureHeader, signedRequest *pb.SignedSnapshotRequest) error {
   111  	if signatureHdr == nil {
   112  		return errors.New("missing signature header")
   113  	}
   114  
   115  	expirationTime := crypto.ExpiresAt(signatureHdr.Creator)
   116  	if !expirationTime.IsZero() && time.Now().After(expirationTime) {
   117  		return errors.New("client identity expired")
   118  	}
   119  
   120  	if err := s.ACLProvider.CheckACLNoChannel(
   121  		resName,
   122  		[]*protoutil.SignedData{{
   123  			Identity:  signatureHdr.Creator,
   124  			Data:      signedRequest.Request,
   125  			Signature: signedRequest.Signature,
   126  		}},
   127  	); err != nil {
   128  		return err
   129  	}
   130  
   131  	return nil
   132  }
   133  
   134  func (s *SnapshotService) getLedger(channelID string) (ledger.PeerLedger, error) {
   135  	if channelID == "" {
   136  		return nil, errors.New("missing channel ID")
   137  	}
   138  
   139  	lgr := s.LedgerGetter.GetLedger(channelID)
   140  	if lgr == nil {
   141  		return nil, errors.Errorf("cannot find ledger for channel %s", channelID)
   142  	}
   143  
   144  	return lgr, nil
   145  }