github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/gossip/state/state.go (about)

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