github.com/anjalikarhana/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  }