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 }