github.com/ewagmig/fabric@v2.1.1+incompatible/gossip/state/state.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package state
     8  
     9  import (
    10  	"bytes"
    11  	"sync"
    12  	"sync/atomic"
    13  	"time"
    14  
    15  	pb "github.com/golang/protobuf/proto"
    16  	"github.com/hyperledger/fabric-protos-go/common"
    17  	proto "github.com/hyperledger/fabric-protos-go/gossip"
    18  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    19  	"github.com/hyperledger/fabric-protos-go/peer"
    20  	"github.com/hyperledger/fabric-protos-go/transientstore"
    21  	vsccErrors "github.com/hyperledger/fabric/common/errors"
    22  	"github.com/hyperledger/fabric/gossip/api"
    23  	"github.com/hyperledger/fabric/gossip/comm"
    24  	common2 "github.com/hyperledger/fabric/gossip/common"
    25  	"github.com/hyperledger/fabric/gossip/discovery"
    26  	"github.com/hyperledger/fabric/gossip/metrics"
    27  	"github.com/hyperledger/fabric/gossip/protoext"
    28  	"github.com/hyperledger/fabric/gossip/util"
    29  	"github.com/hyperledger/fabric/protoutil"
    30  	"github.com/pkg/errors"
    31  )
    32  
    33  // GossipStateProvider is the interface to acquire sequences of the ledger blocks
    34  // capable to full fill missing blocks by running state replication and
    35  // sending request to get missing block to other nodes
    36  type GossipStateProvider interface {
    37  	AddPayload(payload *proto.Payload) error
    38  
    39  	// Stop terminates state transfer object
    40  	Stop()
    41  }
    42  
    43  const (
    44  	defAntiEntropyInterval             = 10 * time.Second
    45  	defAntiEntropyStateResponseTimeout = 3 * time.Second
    46  	defAntiEntropyBatchSize            = 10
    47  
    48  	defChannelBufferSize     = 100
    49  	defAntiEntropyMaxRetries = 3
    50  
    51  	defMaxBlockDistance = 100
    52  
    53  	blocking    = true
    54  	nonBlocking = false
    55  
    56  	enqueueRetryInterval = time.Millisecond * 100
    57  )
    58  
    59  // Configuration keeps state transfer configuration parameters
    60  type Configuration struct {
    61  	AntiEntropyInterval             time.Duration
    62  	AntiEntropyStateResponseTimeout time.Duration
    63  	AntiEntropyBatchSize            uint64
    64  	MaxBlockDistance                int
    65  	AntiEntropyMaxRetries           int
    66  	ChannelBufferSize               int
    67  	EnableStateTransfer             bool
    68  }
    69  
    70  // GossipAdapter defines gossip/communication required interface for state provider
    71  type GossipAdapter interface {
    72  	// Send sends a message to remote peers
    73  	Send(msg *proto.GossipMessage, peers ...*comm.RemotePeer)
    74  
    75  	// Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate.
    76  	// If passThrough is false, the messages are processed by the gossip layer beforehand.
    77  	// If passThrough is true, the gossip layer doesn't intervene and the messages
    78  	// can be used to send a reply back to the sender
    79  	Accept(acceptor common2.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan protoext.ReceivedMessage)
    80  
    81  	// UpdateLedgerHeight updates the ledger height the peer
    82  	// publishes to other peers in the channel
    83  	UpdateLedgerHeight(height uint64, channelID common2.ChannelID)
    84  
    85  	// PeersOfChannel returns the NetworkMembers considered alive
    86  	// and also subscribed to the channel given
    87  	PeersOfChannel(common2.ChannelID) []discovery.NetworkMember
    88  }
    89  
    90  // MCSAdapter adapter of message crypto service interface to bound
    91  // specific APIs required by state transfer service
    92  type MCSAdapter interface {
    93  	// VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
    94  	// sequence number that the block's header contains.
    95  	// else returns error
    96  	VerifyBlock(channelID common2.ChannelID, seqNum uint64, signedBlock *common.Block) error
    97  
    98  	// VerifyByChannel checks that signature is a valid signature of message
    99  	// under a peer's verification key, but also in the context of a specific channel.
   100  	// If the verification succeeded, Verify returns nil meaning no error occurred.
   101  	// If peerIdentity is nil, then the verification fails.
   102  	VerifyByChannel(channelID common2.ChannelID, peerIdentity api.PeerIdentityType, signature, message []byte) error
   103  }
   104  
   105  // ledgerResources defines abilities that the ledger provides
   106  type ledgerResources interface {
   107  	// StoreBlock deliver new block with underlined private data
   108  	// returns missing transaction ids
   109  	StoreBlock(block *common.Block, data util.PvtDataCollections) error
   110  
   111  	// StorePvtData used to persist private date into transient store
   112  	StorePvtData(txid string, privData *transientstore.TxPvtReadWriteSetWithConfigInfo, blckHeight uint64) error
   113  
   114  	// GetPvtDataAndBlockByNum gets block by number and also returns all related private data
   115  	// that requesting peer is eligible for.
   116  	// The order of private data in slice of PvtDataCollections doesn't imply the order of
   117  	// transactions in the block related to these private data, to get the correct placement
   118  	// need to read TxPvtData.SeqInBlock field
   119  	GetPvtDataAndBlockByNum(seqNum uint64, peerAuthInfo protoutil.SignedData) (*common.Block, util.PvtDataCollections, error)
   120  
   121  	// Get recent block sequence number
   122  	LedgerHeight() (uint64, error)
   123  
   124  	// Close ledgerResources
   125  	Close()
   126  }
   127  
   128  // ServicesMediator aggregated adapter to compound all mediator
   129  // required by state transfer into single struct
   130  type ServicesMediator struct {
   131  	GossipAdapter
   132  	MCSAdapter
   133  }
   134  
   135  // GossipStateProviderImpl the implementation of the GossipStateProvider interface
   136  // the struct to handle in memory sliding window of
   137  // new ledger block to be acquired by hyper ledger
   138  type GossipStateProviderImpl struct {
   139  	logger util.Logger
   140  
   141  	// Chain id
   142  	chainID string
   143  
   144  	mediator *ServicesMediator
   145  
   146  	// Queue of payloads which wasn't acquired yet
   147  	payloads PayloadsBuffer
   148  
   149  	ledger ledgerResources
   150  
   151  	stateResponseCh chan protoext.ReceivedMessage
   152  
   153  	stateRequestCh chan protoext.ReceivedMessage
   154  
   155  	stopCh chan struct{}
   156  
   157  	once sync.Once
   158  
   159  	stateTransferActive int32
   160  
   161  	stateMetrics *metrics.StateMetrics
   162  
   163  	requestValidator *stateRequestValidator
   164  
   165  	blockingMode bool
   166  
   167  	config *StateConfig
   168  }
   169  
   170  // stateRequestValidator facilitates validation of the state request messages
   171  type stateRequestValidator struct {
   172  }
   173  
   174  // validate checks for RemoteStateRequest message validity
   175  func (v *stateRequestValidator) validate(request *proto.RemoteStateRequest, batchSize uint64) error {
   176  	if request.StartSeqNum > request.EndSeqNum {
   177  		return errors.Errorf("Invalid sequence interval [%d...%d).", request.StartSeqNum, request.EndSeqNum)
   178  	}
   179  
   180  	if request.EndSeqNum > batchSize+request.StartSeqNum {
   181  		return errors.Errorf("Requesting blocks range [%d-%d) greater than configured allowed"+
   182  			" (%d) batching size for anti-entropy.", request.StartSeqNum, request.EndSeqNum, batchSize)
   183  	}
   184  	return nil
   185  }
   186  
   187  // NewGossipStateProvider creates state provider with coordinator instance
   188  // to orchestrate arrival of private rwsets and blocks before committing them into the ledger.
   189  func NewGossipStateProvider(
   190  	logger util.Logger,
   191  	chainID string,
   192  	services *ServicesMediator,
   193  	ledger ledgerResources,
   194  	stateMetrics *metrics.StateMetrics,
   195  	blockingMode bool,
   196  	config *StateConfig,
   197  ) GossipStateProvider {
   198  	gossipChan, _ := services.Accept(func(message interface{}) bool {
   199  		// Get only data messages
   200  		return protoext.IsDataMsg(message.(*proto.GossipMessage)) &&
   201  			bytes.Equal(message.(*proto.GossipMessage).Channel, []byte(chainID))
   202  	}, false)
   203  
   204  	remoteStateMsgFilter := func(message interface{}) bool {
   205  		receivedMsg := message.(protoext.ReceivedMessage)
   206  		msg := receivedMsg.GetGossipMessage()
   207  		if !(protoext.IsRemoteStateMessage(msg.GossipMessage) || msg.GetPrivateData() != nil) {
   208  			return false
   209  		}
   210  		// Ensure we deal only with messages that belong to this channel
   211  		if !bytes.Equal(msg.Channel, []byte(chainID)) {
   212  			return false
   213  		}
   214  		connInfo := receivedMsg.GetConnectionInfo()
   215  		authErr := services.VerifyByChannel(msg.Channel, connInfo.Identity, connInfo.Auth.Signature, connInfo.Auth.SignedData)
   216  		if authErr != nil {
   217  			logger.Warning("Got unauthorized request from", string(connInfo.Identity))
   218  			return false
   219  		}
   220  		return true
   221  	}
   222  
   223  	// Filter message which are only relevant for nodeMetastate transfer
   224  	_, commChan := services.Accept(remoteStateMsgFilter, true)
   225  
   226  	height, err := ledger.LedgerHeight()
   227  	if height == 0 {
   228  		// Panic here since this is an indication of invalid situation which should not happen in normal
   229  		// code path.
   230  		logger.Panic("Committer height cannot be zero, ledger should include at least one block (genesis).")
   231  	}
   232  
   233  	if err != nil {
   234  		logger.Error("Could not read ledger info to obtain current ledger height due to: ", errors.WithStack(err))
   235  		// Exiting as without ledger it will be impossible
   236  		// to deliver new blocks
   237  		return nil
   238  	}
   239  
   240  	s := &GossipStateProviderImpl{
   241  		logger: logger,
   242  		// MessageCryptoService
   243  		mediator: services,
   244  		// Chain ID
   245  		chainID: chainID,
   246  		// Create a queue for payloads, wrapped in a metrics buffer
   247  		payloads: &metricsBuffer{
   248  			PayloadsBuffer: NewPayloadsBuffer(height),
   249  			sizeMetrics:    stateMetrics.PayloadBufferSize,
   250  			chainID:        chainID,
   251  		},
   252  		ledger:              ledger,
   253  		stateResponseCh:     make(chan protoext.ReceivedMessage, config.StateChannelSize),
   254  		stateRequestCh:      make(chan protoext.ReceivedMessage, config.StateChannelSize),
   255  		stopCh:              make(chan struct{}),
   256  		stateTransferActive: 0,
   257  		once:                sync.Once{},
   258  		stateMetrics:        stateMetrics,
   259  		requestValidator:    &stateRequestValidator{},
   260  		blockingMode:        blockingMode,
   261  		config:              config,
   262  	}
   263  
   264  	logger.Infof("Updating metadata information for channel %s, "+
   265  		"current ledger sequence is at = %d, next expected block is = %d", chainID, height-1, s.payloads.Next())
   266  	logger.Debug("Updating gossip ledger height to", height)
   267  	services.UpdateLedgerHeight(height, common2.ChannelID(s.chainID))
   268  
   269  	// Listen for incoming communication
   270  	go s.receiveAndQueueGossipMessages(gossipChan)
   271  	go s.receiveAndDispatchDirectMessages(commChan)
   272  	// Deliver in order messages into the incoming channel
   273  	go s.deliverPayloads()
   274  	if s.config.StateEnabled {
   275  		// Execute anti entropy to fill missing gaps
   276  		go s.antiEntropy()
   277  	}
   278  	// Taking care of state request messages
   279  	go s.processStateRequests()
   280  
   281  	return s
   282  }
   283  
   284  func (s *GossipStateProviderImpl) receiveAndQueueGossipMessages(ch <-chan *proto.GossipMessage) {
   285  	for msg := range ch {
   286  		s.logger.Debug("Received new message via gossip channel")
   287  		go func(msg *proto.GossipMessage) {
   288  			if !bytes.Equal(msg.Channel, []byte(s.chainID)) {
   289  				s.logger.Warning("Received enqueue for channel",
   290  					string(msg.Channel), "while expecting channel", s.chainID, "ignoring enqueue")
   291  				return
   292  			}
   293  
   294  			dataMsg := msg.GetDataMsg()
   295  			if dataMsg != nil {
   296  				if err := s.addPayload(dataMsg.GetPayload(), nonBlocking); err != nil {
   297  					s.logger.Warningf("Block [%d] received from gossip wasn't added to payload buffer: %v", dataMsg.Payload.SeqNum, err)
   298  					return
   299  				}
   300  
   301  			} else {
   302  				s.logger.Debug("Gossip message received is not of data message type, usually this should not happen.")
   303  			}
   304  		}(msg)
   305  	}
   306  }
   307  
   308  func (s *GossipStateProviderImpl) receiveAndDispatchDirectMessages(ch <-chan protoext.ReceivedMessage) {
   309  	for msg := range ch {
   310  		s.logger.Debug("Dispatching a message", msg)
   311  		go func(msg protoext.ReceivedMessage) {
   312  			gm := msg.GetGossipMessage()
   313  			// Check type of the message
   314  			if protoext.IsRemoteStateMessage(gm.GossipMessage) {
   315  				s.logger.Debug("Handling direct state transfer message")
   316  				// Got state transfer request response
   317  				s.directMessage(msg)
   318  			} else if gm.GetPrivateData() != nil {
   319  				s.logger.Debug("Handling private data collection message")
   320  				// Handling private data replication message
   321  				s.privateDataMessage(msg)
   322  			}
   323  		}(msg)
   324  	}
   325  }
   326  
   327  func (s *GossipStateProviderImpl) privateDataMessage(msg protoext.ReceivedMessage) {
   328  	if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
   329  		s.logger.Warning("Received state transfer request for channel",
   330  			string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
   331  		return
   332  	}
   333  
   334  	gossipMsg := msg.GetGossipMessage()
   335  	pvtDataMsg := gossipMsg.GetPrivateData()
   336  
   337  	if pvtDataMsg.Payload == nil {
   338  		s.logger.Warning("Malformed private data message, no payload provided")
   339  		return
   340  	}
   341  
   342  	collectionName := pvtDataMsg.Payload.CollectionName
   343  	txID := pvtDataMsg.Payload.TxId
   344  	pvtRwSet := pvtDataMsg.Payload.PrivateRwset
   345  
   346  	if len(pvtRwSet) == 0 {
   347  		s.logger.Warning("Malformed private data message, no rwset provided, collection name = ", collectionName)
   348  		return
   349  	}
   350  
   351  	txPvtRwSet := &rwset.TxPvtReadWriteSet{
   352  		DataModel: rwset.TxReadWriteSet_KV,
   353  		NsPvtRwset: []*rwset.NsPvtReadWriteSet{{
   354  			Namespace: pvtDataMsg.Payload.Namespace,
   355  			CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{{
   356  				CollectionName: collectionName,
   357  				Rwset:          pvtRwSet,
   358  			}}},
   359  		},
   360  	}
   361  
   362  	txPvtRwSetWithConfig := &transientstore.TxPvtReadWriteSetWithConfigInfo{
   363  		PvtRwset: txPvtRwSet,
   364  		CollectionConfigs: map[string]*peer.CollectionConfigPackage{
   365  			pvtDataMsg.Payload.Namespace: pvtDataMsg.Payload.CollectionConfigs,
   366  		},
   367  	}
   368  
   369  	if err := s.ledger.StorePvtData(txID, txPvtRwSetWithConfig, pvtDataMsg.Payload.PrivateSimHeight); err != nil {
   370  		s.logger.Errorf("Wasn't able to persist private data for collection %s, due to %s", collectionName, err)
   371  		msg.Ack(err) // Sending NACK to indicate failure of storing collection
   372  	}
   373  
   374  	msg.Ack(nil)
   375  	s.logger.Debug("Private data for collection", collectionName, "has been stored")
   376  }
   377  
   378  func (s *GossipStateProviderImpl) directMessage(msg protoext.ReceivedMessage) {
   379  	s.logger.Debug("[ENTER] -> directMessage")
   380  	defer s.logger.Debug("[EXIT] ->  directMessage")
   381  
   382  	if msg == nil {
   383  		s.logger.Error("Got nil message via end-to-end channel, should not happen!")
   384  		return
   385  	}
   386  
   387  	if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
   388  		s.logger.Warning("Received state transfer request for channel",
   389  			string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
   390  		return
   391  	}
   392  
   393  	incoming := msg.GetGossipMessage()
   394  
   395  	if incoming.GetStateRequest() != nil {
   396  		if len(s.stateRequestCh) < s.config.StateChannelSize {
   397  			// Forward state request to the channel, if there are too
   398  			// many message of state request ignore to avoid flooding.
   399  			s.stateRequestCh <- msg
   400  		}
   401  	} else if incoming.GetStateResponse() != nil {
   402  		// If no state transfer procedure activate there is
   403  		// no reason to process the message
   404  		if atomic.LoadInt32(&s.stateTransferActive) == 1 {
   405  			// Send signal of state response message
   406  			s.stateResponseCh <- msg
   407  		}
   408  	}
   409  }
   410  
   411  func (s *GossipStateProviderImpl) processStateRequests() {
   412  	for {
   413  		msg, stillOpen := <-s.stateRequestCh
   414  		if !stillOpen {
   415  			return
   416  		}
   417  		s.handleStateRequest(msg)
   418  	}
   419  }
   420  
   421  // handleStateRequest handles state request message, validate batch size, reads current leader state to
   422  // obtain required blocks, builds response message and send it back
   423  func (s *GossipStateProviderImpl) handleStateRequest(msg protoext.ReceivedMessage) {
   424  	if msg == nil {
   425  		return
   426  	}
   427  	request := msg.GetGossipMessage().GetStateRequest()
   428  
   429  	if err := s.requestValidator.validate(request, s.config.StateBatchSize); err != nil {
   430  		s.logger.Errorf("State request validation failed, %s. Ignoring request...", err)
   431  		return
   432  	}
   433  
   434  	currentHeight, err := s.ledger.LedgerHeight()
   435  	if err != nil {
   436  		s.logger.Errorf("Cannot access to current ledger height, due to %+v", err)
   437  		return
   438  	}
   439  	if currentHeight < request.EndSeqNum {
   440  		s.logger.Warningf("Received state request to transfer blocks with sequence numbers higher  [%d...%d] "+
   441  			"than available in ledger (%d)", request.StartSeqNum, request.StartSeqNum, currentHeight)
   442  	}
   443  
   444  	endSeqNum := min(currentHeight, request.EndSeqNum)
   445  
   446  	response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)}
   447  	for seqNum := request.StartSeqNum; seqNum <= endSeqNum; seqNum++ {
   448  		s.logger.Debug("Reading block ", seqNum, " with private data from the coordinator service")
   449  		connInfo := msg.GetConnectionInfo()
   450  		peerAuthInfo := protoutil.SignedData{
   451  			Data:      connInfo.Auth.SignedData,
   452  			Signature: connInfo.Auth.Signature,
   453  			Identity:  connInfo.Identity,
   454  		}
   455  		block, pvtData, err := s.ledger.GetPvtDataAndBlockByNum(seqNum, peerAuthInfo)
   456  
   457  		if err != nil {
   458  			s.logger.Errorf("cannot read block number %d from ledger, because %+v, skipping...", seqNum, err)
   459  			continue
   460  		}
   461  
   462  		if block == nil {
   463  			s.logger.Errorf("Wasn't able to read block with sequence number %d from ledger, skipping....", seqNum)
   464  			continue
   465  		}
   466  
   467  		blockBytes, err := pb.Marshal(block)
   468  
   469  		if err != nil {
   470  			s.logger.Errorf("Could not marshal block: %+v", errors.WithStack(err))
   471  			continue
   472  		}
   473  
   474  		var pvtBytes [][]byte
   475  		if pvtData != nil {
   476  			// Marshal private data
   477  			pvtBytes, err = pvtData.Marshal()
   478  			if err != nil {
   479  				s.logger.Errorf("Failed to marshal private rwset for block %d due to %+v", seqNum, errors.WithStack(err))
   480  				continue
   481  			}
   482  		}
   483  
   484  		// Appending result to the response
   485  		response.Payloads = append(response.Payloads, &proto.Payload{
   486  			SeqNum:      seqNum,
   487  			Data:        blockBytes,
   488  			PrivateData: pvtBytes,
   489  		})
   490  	}
   491  	// Sending back response with missing blocks
   492  	msg.Respond(&proto.GossipMessage{
   493  		// Copy nonce field from the request, so it will be possible to match response
   494  		Nonce:   msg.GetGossipMessage().Nonce,
   495  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   496  		Channel: []byte(s.chainID),
   497  		Content: &proto.GossipMessage_StateResponse{StateResponse: response},
   498  	})
   499  }
   500  
   501  func (s *GossipStateProviderImpl) handleStateResponse(msg protoext.ReceivedMessage) (uint64, error) {
   502  	max := uint64(0)
   503  	// Send signal that response for given nonce has been received
   504  	response := msg.GetGossipMessage().GetStateResponse()
   505  	// Extract payloads, verify and push into buffer
   506  	if len(response.GetPayloads()) == 0 {
   507  		return uint64(0), errors.New("Received state transfer response without payload")
   508  	}
   509  	for _, payload := range response.GetPayloads() {
   510  		s.logger.Debugf("Received payload with sequence number %d.", payload.SeqNum)
   511  		block, err := protoutil.UnmarshalBlock(payload.Data)
   512  		if err != nil {
   513  			s.logger.Warningf("Error unmarshaling payload to block for sequence number %d, due to %+v", payload.SeqNum, err)
   514  			return uint64(0), err
   515  		}
   516  
   517  		if err := s.mediator.VerifyBlock(common2.ChannelID(s.chainID), payload.SeqNum, block); err != nil {
   518  			err = errors.WithStack(err)
   519  			s.logger.Warningf("Error verifying block with sequence number %d, due to %+v", payload.SeqNum, err)
   520  			return uint64(0), err
   521  		}
   522  		if max < payload.SeqNum {
   523  			max = payload.SeqNum
   524  		}
   525  
   526  		err = s.addPayload(payload, blocking)
   527  		if err != nil {
   528  			s.logger.Warningf("Block [%d] received from block transfer wasn't added to payload buffer: %v", payload.SeqNum, err)
   529  		}
   530  	}
   531  	return max, nil
   532  }
   533  
   534  // Stop function sends halting signal to all go routines
   535  func (s *GossipStateProviderImpl) Stop() {
   536  	// Make sure stop won't be executed twice
   537  	// and stop channel won't be used again
   538  	s.once.Do(func() {
   539  		close(s.stopCh)
   540  		// Close all resources
   541  		s.ledger.Close()
   542  		close(s.stateRequestCh)
   543  		close(s.stateResponseCh)
   544  	})
   545  }
   546  
   547  func (s *GossipStateProviderImpl) deliverPayloads() {
   548  	for {
   549  		select {
   550  		// Wait for notification that next seq has arrived
   551  		case <-s.payloads.Ready():
   552  			s.logger.Debugf("[%s] Ready to transfer payloads (blocks) to the ledger, next block number is = [%d]", s.chainID, s.payloads.Next())
   553  			// Collect all subsequent payloads
   554  			for payload := s.payloads.Pop(); payload != nil; payload = s.payloads.Pop() {
   555  				rawBlock := &common.Block{}
   556  				if err := pb.Unmarshal(payload.Data, rawBlock); err != nil {
   557  					s.logger.Errorf("Error getting block with seqNum = %d due to (%+v)...dropping block", payload.SeqNum, errors.WithStack(err))
   558  					continue
   559  				}
   560  				if rawBlock.Data == nil || rawBlock.Header == nil {
   561  					s.logger.Errorf("Block with claimed sequence %d has no header (%v) or data (%v)",
   562  						payload.SeqNum, rawBlock.Header, rawBlock.Data)
   563  					continue
   564  				}
   565  				s.logger.Debugf("[%s] Transferring block [%d] with %d transaction(s) to the ledger", s.chainID, payload.SeqNum, len(rawBlock.Data.Data))
   566  
   567  				// Read all private data into slice
   568  				var p util.PvtDataCollections
   569  				if payload.PrivateData != nil {
   570  					err := p.Unmarshal(payload.PrivateData)
   571  					if err != nil {
   572  						s.logger.Errorf("Wasn't able to unmarshal private data for block seqNum = %d due to (%+v)...dropping block", payload.SeqNum, errors.WithStack(err))
   573  						continue
   574  					}
   575  				}
   576  				if err := s.commitBlock(rawBlock, p); err != nil {
   577  					if executionErr, isExecutionErr := err.(*vsccErrors.VSCCExecutionFailureError); isExecutionErr {
   578  						s.logger.Errorf("Failed executing VSCC due to %v. Aborting chain processing", executionErr)
   579  						return
   580  					}
   581  					s.logger.Panicf("Cannot commit block to the ledger due to %+v", errors.WithStack(err))
   582  				}
   583  			}
   584  		case <-s.stopCh:
   585  			s.logger.Debug("State provider has been stopped, finishing to push new blocks.")
   586  			return
   587  		}
   588  	}
   589  }
   590  
   591  func (s *GossipStateProviderImpl) antiEntropy() {
   592  	defer s.logger.Debug("State Provider stopped, stopping anti entropy procedure.")
   593  
   594  	for {
   595  		select {
   596  		case <-s.stopCh:
   597  			return
   598  		case <-time.After(s.config.StateCheckInterval):
   599  			ourHeight, err := s.ledger.LedgerHeight()
   600  			if err != nil {
   601  				// Unable to read from ledger continue to the next round
   602  				s.logger.Errorf("Cannot obtain ledger height, due to %+v", errors.WithStack(err))
   603  				continue
   604  			}
   605  			if ourHeight == 0 {
   606  				s.logger.Error("Ledger reported block height of 0 but this should be impossible")
   607  				continue
   608  			}
   609  			maxHeight := s.maxAvailableLedgerHeight()
   610  			if ourHeight >= maxHeight {
   611  				continue
   612  			}
   613  
   614  			s.requestBlocksInRange(uint64(ourHeight), uint64(maxHeight)-1)
   615  		}
   616  	}
   617  }
   618  
   619  // maxAvailableLedgerHeight iterates over all available peers and checks advertised meta state to
   620  // find maximum available ledger height across peers
   621  func (s *GossipStateProviderImpl) maxAvailableLedgerHeight() uint64 {
   622  	max := uint64(0)
   623  	for _, p := range s.mediator.PeersOfChannel(common2.ChannelID(s.chainID)) {
   624  		if p.Properties == nil {
   625  			s.logger.Debug("Peer", p.PreferredEndpoint(), "doesn't have properties, skipping it")
   626  			continue
   627  		}
   628  		peerHeight := p.Properties.LedgerHeight
   629  		if max < peerHeight {
   630  			max = peerHeight
   631  		}
   632  	}
   633  	return max
   634  }
   635  
   636  // requestBlocksInRange capable to acquire blocks with sequence
   637  // numbers in the range [start...end).
   638  func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) {
   639  	atomic.StoreInt32(&s.stateTransferActive, 1)
   640  	defer atomic.StoreInt32(&s.stateTransferActive, 0)
   641  
   642  	for prev := start; prev <= end; {
   643  		next := min(end, prev+s.config.StateBatchSize)
   644  
   645  		gossipMsg := s.stateRequestMessage(prev, next)
   646  
   647  		responseReceived := false
   648  		tryCounts := 0
   649  
   650  		for !responseReceived {
   651  			if tryCounts > s.config.StateMaxRetries {
   652  				s.logger.Warningf("Wasn't  able to get blocks in range [%d...%d), after %d retries",
   653  					prev, next, tryCounts)
   654  				return
   655  			}
   656  			// Select peers to ask for blocks
   657  			peer, err := s.selectPeerToRequestFrom(next)
   658  			if err != nil {
   659  				s.logger.Warningf("Cannot send state request for blocks in range [%d...%d), due to %+v",
   660  					prev, next, errors.WithStack(err))
   661  				return
   662  			}
   663  
   664  			s.logger.Debugf("State transfer, with peer %s, requesting blocks in range [%d...%d), "+
   665  				"for chainID %s", peer.Endpoint, prev, next, s.chainID)
   666  
   667  			s.mediator.Send(gossipMsg, peer)
   668  			tryCounts++
   669  
   670  			// Wait until timeout or response arrival
   671  			select {
   672  			case msg, stillOpen := <-s.stateResponseCh:
   673  				if !stillOpen {
   674  					return
   675  				}
   676  				if msg.GetGossipMessage().Nonce !=
   677  					gossipMsg.Nonce {
   678  					continue
   679  				}
   680  				// Got corresponding response for state request, can continue
   681  				index, err := s.handleStateResponse(msg)
   682  				if err != nil {
   683  					s.logger.Warningf("Wasn't able to process state response for "+
   684  						"blocks [%d...%d], due to %+v", prev, next, errors.WithStack(err))
   685  					continue
   686  				}
   687  				prev = index + 1
   688  				responseReceived = true
   689  			case <-time.After(s.config.StateResponseTimeout):
   690  			}
   691  		}
   692  	}
   693  }
   694  
   695  // stateRequestMessage generates state request message for given blocks in range [beginSeq...endSeq]
   696  func (s *GossipStateProviderImpl) stateRequestMessage(beginSeq uint64, endSeq uint64) *proto.GossipMessage {
   697  	return &proto.GossipMessage{
   698  		Nonce:   util.RandomUInt64(),
   699  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   700  		Channel: []byte(s.chainID),
   701  		Content: &proto.GossipMessage_StateRequest{
   702  			StateRequest: &proto.RemoteStateRequest{
   703  				StartSeqNum: beginSeq,
   704  				EndSeqNum:   endSeq,
   705  			},
   706  		},
   707  	}
   708  }
   709  
   710  // selectPeerToRequestFrom selects peer which has required blocks to ask missing blocks from
   711  func (s *GossipStateProviderImpl) selectPeerToRequestFrom(height uint64) (*comm.RemotePeer, error) {
   712  	// Filter peers which posses required range of missing blocks
   713  	peers := s.filterPeers(s.hasRequiredHeight(height))
   714  
   715  	n := len(peers)
   716  	if n == 0 {
   717  		return nil, errors.New("there are no peers to ask for missing blocks from")
   718  	}
   719  
   720  	// Select peer to ask for blocks
   721  	return peers[util.RandomInt(n)], nil
   722  }
   723  
   724  // filterPeers returns list of peers which aligns the predicate provided
   725  func (s *GossipStateProviderImpl) filterPeers(predicate func(peer discovery.NetworkMember) bool) []*comm.RemotePeer {
   726  	var peers []*comm.RemotePeer
   727  
   728  	for _, member := range s.mediator.PeersOfChannel(common2.ChannelID(s.chainID)) {
   729  		if predicate(member) {
   730  			peers = append(peers, &comm.RemotePeer{Endpoint: member.PreferredEndpoint(), PKIID: member.PKIid})
   731  		}
   732  	}
   733  
   734  	return peers
   735  }
   736  
   737  // hasRequiredHeight returns predicate which is capable to filter peers with ledger height above than indicated
   738  // by provided input parameter
   739  func (s *GossipStateProviderImpl) hasRequiredHeight(height uint64) func(peer discovery.NetworkMember) bool {
   740  	return func(peer discovery.NetworkMember) bool {
   741  		if peer.Properties != nil {
   742  			return peer.Properties.LedgerHeight >= height
   743  		}
   744  		s.logger.Debug(peer.PreferredEndpoint(), "doesn't have properties")
   745  		return false
   746  	}
   747  }
   748  
   749  // AddPayload adds new payload into state.
   750  func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error {
   751  	return s.addPayload(payload, s.blockingMode)
   752  }
   753  
   754  // addPayload adds new payload into state. It may (or may not) block according to the
   755  // given parameter. If it gets a block while in blocking mode - it would wait until
   756  // the block is sent into the payloads buffer.
   757  // Else - it may drop the block, if the payload buffer is too full.
   758  func (s *GossipStateProviderImpl) addPayload(payload *proto.Payload, blockingMode bool) error {
   759  	if payload == nil {
   760  		return errors.New("Given payload is nil")
   761  	}
   762  	s.logger.Debugf("[%s] Adding payload to local buffer, blockNum = [%d]", s.chainID, payload.SeqNum)
   763  	height, err := s.ledger.LedgerHeight()
   764  	if err != nil {
   765  		return errors.Wrap(err, "Failed obtaining ledger height")
   766  	}
   767  
   768  	if !blockingMode && payload.SeqNum-height >= uint64(s.config.StateBlockBufferSize) {
   769  		return errors.Errorf("Ledger height is at %d, cannot enqueue block with sequence of %d", height, payload.SeqNum)
   770  	}
   771  
   772  	for blockingMode && s.payloads.Size() > s.config.StateBlockBufferSize*2 {
   773  		time.Sleep(enqueueRetryInterval)
   774  	}
   775  
   776  	s.payloads.Push(payload)
   777  	s.logger.Debugf("Blocks payloads buffer size for channel [%s] is %d blocks", s.chainID, s.payloads.Size())
   778  	return nil
   779  }
   780  
   781  func (s *GossipStateProviderImpl) commitBlock(block *common.Block, pvtData util.PvtDataCollections) error {
   782  
   783  	t1 := time.Now()
   784  
   785  	// Commit block with available private transactions
   786  	if err := s.ledger.StoreBlock(block, pvtData); err != nil {
   787  		s.logger.Errorf("Got error while committing(%+v)", errors.WithStack(err))
   788  		return err
   789  	}
   790  
   791  	sinceT1 := time.Since(t1)
   792  	s.stateMetrics.CommitDuration.With("channel", s.chainID).Observe(sinceT1.Seconds())
   793  
   794  	// Update ledger height
   795  	s.mediator.UpdateLedgerHeight(block.Header.Number+1, common2.ChannelID(s.chainID))
   796  	s.logger.Debugf("[%s] Committed block [%d] with %d transaction(s)",
   797  		s.chainID, block.Header.Number, len(block.Data.Data))
   798  
   799  	s.stateMetrics.Height.With("channel", s.chainID).Set(float64(block.Header.Number + 1))
   800  
   801  	return nil
   802  }
   803  
   804  func min(a uint64, b uint64) uint64 {
   805  	return b ^ ((a ^ b) & (-(uint64(a-b) >> 63)))
   806  }