github.com/defanghe/fabric@v2.1.1+incompatible/internal/peer/common/deliverclient.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package common 8 9 import ( 10 cb "github.com/hyperledger/fabric-protos-go/common" 11 ab "github.com/hyperledger/fabric-protos-go/orderer" 12 pb "github.com/hyperledger/fabric-protos-go/peer" 13 "github.com/hyperledger/fabric/common/flogging" 14 "github.com/hyperledger/fabric/common/util" 15 "github.com/hyperledger/fabric/internal/pkg/identity" 16 "github.com/hyperledger/fabric/protoutil" 17 "github.com/pkg/errors" 18 ) 19 20 var ( 21 logger = flogging.MustGetLogger("cli.common") 22 23 seekNewest = &ab.SeekPosition{ 24 Type: &ab.SeekPosition_Newest{ 25 Newest: &ab.SeekNewest{}, 26 }, 27 } 28 seekOldest = &ab.SeekPosition{ 29 Type: &ab.SeekPosition_Oldest{ 30 Oldest: &ab.SeekOldest{}, 31 }, 32 } 33 ) 34 35 // DeliverClient holds the necessary information to connect a client 36 // to an orderer/peer deliver service 37 type DeliverClient struct { 38 Signer identity.SignerSerializer 39 Service ab.AtomicBroadcast_DeliverClient 40 ChannelID string 41 TLSCertHash []byte 42 BestEffort bool 43 } 44 45 func (d *DeliverClient) seekSpecified(blockNumber uint64) error { 46 seekPosition := &ab.SeekPosition{ 47 Type: &ab.SeekPosition_Specified{ 48 Specified: &ab.SeekSpecified{ 49 Number: blockNumber, 50 }, 51 }, 52 } 53 env := seekHelper(d.ChannelID, seekPosition, d.TLSCertHash, d.Signer, d.BestEffort) 54 return d.Service.Send(env) 55 } 56 57 func (d *DeliverClient) seekOldest() error { 58 env := seekHelper(d.ChannelID, seekOldest, d.TLSCertHash, d.Signer, d.BestEffort) 59 return d.Service.Send(env) 60 } 61 62 func (d *DeliverClient) seekNewest() error { 63 env := seekHelper(d.ChannelID, seekNewest, d.TLSCertHash, d.Signer, d.BestEffort) 64 return d.Service.Send(env) 65 } 66 67 func (d *DeliverClient) readBlock() (*cb.Block, error) { 68 msg, err := d.Service.Recv() 69 if err != nil { 70 return nil, errors.Wrap(err, "error receiving") 71 } 72 switch t := msg.Type.(type) { 73 case *ab.DeliverResponse_Status: 74 logger.Infof("Expect block, but got status: %v", t) 75 return nil, errors.Errorf("can't read the block: %v", t) 76 case *ab.DeliverResponse_Block: 77 logger.Infof("Received block: %v", t.Block.Header.Number) 78 if resp, err := d.Service.Recv(); err != nil { // Flush the success message 79 logger.Errorf("Failed to flush success message: %s", err) 80 } else if status := resp.GetStatus(); status != cb.Status_SUCCESS { 81 logger.Errorf("Expect status to be SUCCESS, got: %s", status) 82 } 83 84 return t.Block, nil 85 default: 86 return nil, errors.Errorf("response error: unknown type %T", t) 87 } 88 } 89 90 // GetSpecifiedBlock gets the specified block from a peer/orderer's deliver 91 // service 92 func (d *DeliverClient) GetSpecifiedBlock(num uint64) (*cb.Block, error) { 93 err := d.seekSpecified(num) 94 if err != nil { 95 return nil, errors.WithMessage(err, "error getting specified block") 96 } 97 98 return d.readBlock() 99 } 100 101 // GetOldestBlock gets the oldest block from a peer/orderer's deliver service 102 func (d *DeliverClient) GetOldestBlock() (*cb.Block, error) { 103 err := d.seekOldest() 104 if err != nil { 105 return nil, errors.WithMessage(err, "error getting oldest block") 106 } 107 108 return d.readBlock() 109 } 110 111 // GetNewestBlock gets the newest block from a peer/orderer's deliver service 112 func (d *DeliverClient) GetNewestBlock() (*cb.Block, error) { 113 err := d.seekNewest() 114 if err != nil { 115 return nil, errors.WithMessage(err, "error getting newest block") 116 } 117 118 return d.readBlock() 119 } 120 121 // Close closes a deliver client's connection 122 func (d *DeliverClient) Close() error { 123 return d.Service.CloseSend() 124 } 125 126 func seekHelper( 127 channelID string, 128 position *ab.SeekPosition, 129 tlsCertHash []byte, 130 signer identity.SignerSerializer, 131 bestEffort bool, 132 ) *cb.Envelope { 133 seekInfo := &ab.SeekInfo{ 134 Start: position, 135 Stop: position, 136 Behavior: ab.SeekInfo_BLOCK_UNTIL_READY, 137 } 138 139 if bestEffort { 140 seekInfo.ErrorResponse = ab.SeekInfo_BEST_EFFORT 141 } 142 143 env, err := protoutil.CreateSignedEnvelopeWithTLSBinding( 144 cb.HeaderType_DELIVER_SEEK_INFO, 145 channelID, 146 signer, 147 seekInfo, 148 int32(0), 149 uint64(0), 150 tlsCertHash, 151 ) 152 if err != nil { 153 logger.Errorf("Error signing envelope: %s", err) 154 return nil 155 } 156 157 return env 158 } 159 160 type ordererDeliverService struct { 161 ab.AtomicBroadcast_DeliverClient 162 } 163 164 // NewDeliverClientForOrderer creates a new DeliverClient from an OrdererClient 165 func NewDeliverClientForOrderer(channelID string, signer identity.SignerSerializer, bestEffort bool) (*DeliverClient, error) { 166 var tlsCertHash []byte 167 oc, err := NewOrdererClientFromEnv() 168 if err != nil { 169 return nil, errors.WithMessage(err, "failed to create deliver client for orderer") 170 } 171 172 dc, err := oc.Deliver() 173 if err != nil { 174 return nil, errors.WithMessage(err, "failed to create deliver client for orderer") 175 } 176 // check for client certificate and create hash if present 177 if len(oc.Certificate().Certificate) > 0 { 178 tlsCertHash = util.ComputeSHA256(oc.Certificate().Certificate[0]) 179 } 180 ds := &ordererDeliverService{dc} 181 o := &DeliverClient{ 182 Signer: signer, 183 Service: ds, 184 ChannelID: channelID, 185 TLSCertHash: tlsCertHash, 186 BestEffort: bestEffort, 187 } 188 return o, nil 189 } 190 191 type peerDeliverService struct { 192 pb.Deliver_DeliverClient 193 } 194 195 // NewDeliverClientForPeer creates a new DeliverClient from a PeerClient 196 func NewDeliverClientForPeer(channelID string, signer identity.SignerSerializer, bestEffort bool) (*DeliverClient, error) { 197 var tlsCertHash []byte 198 pc, err := NewPeerClientFromEnv() 199 if err != nil { 200 return nil, errors.WithMessage(err, "failed to create deliver client for peer") 201 } 202 203 d, err := pc.Deliver() 204 if err != nil { 205 return nil, errors.WithMessage(err, "failed to create deliver client for peer") 206 } 207 208 // check for client certificate and create hash if present 209 if len(pc.Certificate().Certificate) > 0 { 210 tlsCertHash = util.ComputeSHA256(pc.Certificate().Certificate[0]) 211 } 212 ds := &peerDeliverService{d} 213 p := &DeliverClient{ 214 Signer: signer, 215 Service: ds, 216 ChannelID: channelID, 217 TLSCertHash: tlsCertHash, 218 BestEffort: bestEffort, 219 } 220 return p, nil 221 } 222 223 func (p *peerDeliverService) Recv() (*ab.DeliverResponse, error) { 224 pbResp, err := p.Deliver_DeliverClient.Recv() 225 if err != nil { 226 return nil, errors.Wrap(err, "error receiving from peer deliver service") 227 } 228 229 abResp := &ab.DeliverResponse{} 230 231 switch t := pbResp.Type.(type) { 232 case *pb.DeliverResponse_Status: 233 abResp.Type = &ab.DeliverResponse_Status{Status: t.Status} 234 case *pb.DeliverResponse_Block: 235 abResp.Type = &ab.DeliverResponse_Block{Block: t.Block} 236 default: 237 return nil, errors.Errorf("response error: unknown type %T", t) 238 } 239 240 return abResp, nil 241 }