github.com/yous1230/fabric@v2.0.0-beta.0.20191224111736-74345bee6ac2+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  	// Chain id
   140  	chainID string
   141  
   142  	mediator *ServicesMediator
   143  
   144  	// Queue of payloads which wasn't acquired yet
   145  	payloads PayloadsBuffer
   146  
   147  	ledger ledgerResources
   148  
   149  	stateResponseCh chan protoext.ReceivedMessage
   150  
   151  	stateRequestCh chan protoext.ReceivedMessage
   152  
   153  	stopCh chan struct{}
   154  
   155  	once sync.Once
   156  
   157  	stateTransferActive int32
   158  
   159  	stateMetrics *metrics.StateMetrics
   160  
   161  	requestValidator *stateRequestValidator
   162  
   163  	blockingMode bool
   164  
   165  	config *StateConfig
   166  }
   167  
   168  var logger = util.GetLogger(util.StateLogger, "")
   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  	chainID string,
   191  	services *ServicesMediator,
   192  	ledger ledgerResources,
   193  	stateMetrics *metrics.StateMetrics,
   194  	blockingMode bool,
   195  	config *StateConfig,
   196  ) GossipStateProvider {
   197  
   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  		// MessageCryptoService
   242  		mediator: services,
   243  		// Chain ID
   244  		chainID: chainID,
   245  		// Create a queue for payloads, wrapped in a metrics buffer
   246  		payloads: &metricsBuffer{
   247  			PayloadsBuffer: NewPayloadsBuffer(height),
   248  			sizeMetrics:    stateMetrics.PayloadBufferSize,
   249  			chainID:        chainID,
   250  		},
   251  		ledger:              ledger,
   252  		stateResponseCh:     make(chan protoext.ReceivedMessage, config.StateChannelSize),
   253  		stateRequestCh:      make(chan protoext.ReceivedMessage, config.StateChannelSize),
   254  		stopCh:              make(chan struct{}),
   255  		stateTransferActive: 0,
   256  		once:                sync.Once{},
   257  		stateMetrics:        stateMetrics,
   258  		requestValidator:    &stateRequestValidator{},
   259  		blockingMode:        blockingMode,
   260  		config:              config,
   261  	}
   262  
   263  	logger.Infof("Updating metadata information for channel %s, "+
   264  		"current ledger sequence is at = %d, next expected block is = %d", chainID, height-1, s.payloads.Next())
   265  	logger.Debug("Updating gossip ledger height to", height)
   266  	services.UpdateLedgerHeight(height, common2.ChannelID(s.chainID))
   267  
   268  	// Listen for incoming communication
   269  	go s.receiveAndQueueGossipMessages(gossipChan)
   270  	go s.receiveAndDispatchDirectMessages(commChan)
   271  	// Deliver in order messages into the incoming channel
   272  	go s.deliverPayloads()
   273  	if s.config.StateEnabled {
   274  		// Execute anti entropy to fill missing gaps
   275  		go s.antiEntropy()
   276  	}
   277  	// Taking care of state request messages
   278  	go s.processStateRequests()
   279  
   280  	return s
   281  }
   282  
   283  func (s *GossipStateProviderImpl) receiveAndQueueGossipMessages(ch <-chan *proto.GossipMessage) {
   284  	for msg := range ch {
   285  		logger.Debug("Received new message via gossip channel")
   286  		go func(msg *proto.GossipMessage) {
   287  			if !bytes.Equal(msg.Channel, []byte(s.chainID)) {
   288  				logger.Warning("Received enqueue for channel",
   289  					string(msg.Channel), "while expecting channel", s.chainID, "ignoring enqueue")
   290  				return
   291  			}
   292  
   293  			dataMsg := msg.GetDataMsg()
   294  			if dataMsg != nil {
   295  				if err := s.addPayload(dataMsg.GetPayload(), nonBlocking); err != nil {
   296  					logger.Warningf("Block [%d] received from gossip wasn't added to payload buffer: %v", dataMsg.Payload.SeqNum, err)
   297  					return
   298  				}
   299  
   300  			} else {
   301  				logger.Debug("Gossip message received is not of data message type, usually this should not happen.")
   302  			}
   303  		}(msg)
   304  	}
   305  }
   306  
   307  func (s *GossipStateProviderImpl) receiveAndDispatchDirectMessages(ch <-chan protoext.ReceivedMessage) {
   308  	for msg := range ch {
   309  		logger.Debug("Dispatching a message", msg)
   310  		go func(msg protoext.ReceivedMessage) {
   311  			gm := msg.GetGossipMessage()
   312  			// Check type of the message
   313  			if protoext.IsRemoteStateMessage(gm.GossipMessage) {
   314  				logger.Debug("Handling direct state transfer message")
   315  				// Got state transfer request response
   316  				s.directMessage(msg)
   317  			} else if gm.GetPrivateData() != nil {
   318  				logger.Debug("Handling private data collection message")
   319  				// Handling private data replication message
   320  				s.privateDataMessage(msg)
   321  			}
   322  		}(msg)
   323  	}
   324  }
   325  
   326  func (s *GossipStateProviderImpl) privateDataMessage(msg protoext.ReceivedMessage) {
   327  	if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
   328  		logger.Warning("Received state transfer request for channel",
   329  			string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
   330  		return
   331  	}
   332  
   333  	gossipMsg := msg.GetGossipMessage()
   334  	pvtDataMsg := gossipMsg.GetPrivateData()
   335  
   336  	if pvtDataMsg.Payload == nil {
   337  		logger.Warning("Malformed private data message, no payload provided")
   338  		return
   339  	}
   340  
   341  	collectionName := pvtDataMsg.Payload.CollectionName
   342  	txID := pvtDataMsg.Payload.TxId
   343  	pvtRwSet := pvtDataMsg.Payload.PrivateRwset
   344  
   345  	if len(pvtRwSet) == 0 {
   346  		logger.Warning("Malformed private data message, no rwset provided, collection name = ", collectionName)
   347  		return
   348  	}
   349  
   350  	txPvtRwSet := &rwset.TxPvtReadWriteSet{
   351  		DataModel: rwset.TxReadWriteSet_KV,
   352  		NsPvtRwset: []*rwset.NsPvtReadWriteSet{{
   353  			Namespace: pvtDataMsg.Payload.Namespace,
   354  			CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{{
   355  				CollectionName: collectionName,
   356  				Rwset:          pvtRwSet,
   357  			}}},
   358  		},
   359  	}
   360  
   361  	txPvtRwSetWithConfig := &transientstore.TxPvtReadWriteSetWithConfigInfo{
   362  		PvtRwset: txPvtRwSet,
   363  		CollectionConfigs: map[string]*peer.CollectionConfigPackage{
   364  			pvtDataMsg.Payload.Namespace: pvtDataMsg.Payload.CollectionConfigs,
   365  		},
   366  	}
   367  
   368  	if err := s.ledger.StorePvtData(txID, txPvtRwSetWithConfig, pvtDataMsg.Payload.PrivateSimHeight); err != nil {
   369  		logger.Errorf("Wasn't able to persist private data for collection %s, due to %s", collectionName, err)
   370  		msg.Ack(err) // Sending NACK to indicate failure of storing collection
   371  	}
   372  
   373  	msg.Ack(nil)
   374  	logger.Debug("Private data for collection", collectionName, "has been stored")
   375  }
   376  
   377  func (s *GossipStateProviderImpl) directMessage(msg protoext.ReceivedMessage) {
   378  	logger.Debug("[ENTER] -> directMessage")
   379  	defer logger.Debug("[EXIT] ->  directMessage")
   380  
   381  	if msg == nil {
   382  		logger.Error("Got nil message via end-to-end channel, should not happen!")
   383  		return
   384  	}
   385  
   386  	if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
   387  		logger.Warning("Received state transfer request for channel",
   388  			string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
   389  		return
   390  	}
   391  
   392  	incoming := msg.GetGossipMessage()
   393  
   394  	if incoming.GetStateRequest() != nil {
   395  		if len(s.stateRequestCh) < s.config.StateChannelSize {
   396  			// Forward state request to the channel, if there are too
   397  			// many message of state request ignore to avoid flooding.
   398  			s.stateRequestCh <- msg
   399  		}
   400  	} else if incoming.GetStateResponse() != nil {
   401  		// If no state transfer procedure activate there is
   402  		// no reason to process the message
   403  		if atomic.LoadInt32(&s.stateTransferActive) == 1 {
   404  			// Send signal of state response message
   405  			s.stateResponseCh <- msg
   406  		}
   407  	}
   408  }
   409  
   410  func (s *GossipStateProviderImpl) processStateRequests() {
   411  	for {
   412  		msg, stillOpen := <-s.stateRequestCh
   413  		if !stillOpen {
   414  			return
   415  		}
   416  		s.handleStateRequest(msg)
   417  	}
   418  }
   419  
   420  // handleStateRequest handles state request message, validate batch size, reads current leader state to
   421  // obtain required blocks, builds response message and send it back
   422  func (s *GossipStateProviderImpl) handleStateRequest(msg protoext.ReceivedMessage) {
   423  	if msg == nil {
   424  		return
   425  	}
   426  	request := msg.GetGossipMessage().GetStateRequest()
   427  
   428  	if err := s.requestValidator.validate(request, s.config.StateBatchSize); err != nil {
   429  		logger.Errorf("State request validation failed, %s. Ignoring request...", err)
   430  		return
   431  	}
   432  
   433  	currentHeight, err := s.ledger.LedgerHeight()
   434  	if err != nil {
   435  		logger.Errorf("Cannot access to current ledger height, due to %+v", err)
   436  		return
   437  	}
   438  	if currentHeight < request.EndSeqNum {
   439  		logger.Warningf("Received state request to transfer blocks with sequence numbers higher  [%d...%d] "+
   440  			"than available in ledger (%d)", request.StartSeqNum, request.StartSeqNum, currentHeight)
   441  	}
   442  
   443  	endSeqNum := min(currentHeight, request.EndSeqNum)
   444  
   445  	response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)}
   446  	for seqNum := request.StartSeqNum; seqNum <= endSeqNum; seqNum++ {
   447  		logger.Debug("Reading block ", seqNum, " with private data from the coordinator service")
   448  		connInfo := msg.GetConnectionInfo()
   449  		peerAuthInfo := protoutil.SignedData{
   450  			Data:      connInfo.Auth.SignedData,
   451  			Signature: connInfo.Auth.Signature,
   452  			Identity:  connInfo.Identity,
   453  		}
   454  		block, pvtData, err := s.ledger.GetPvtDataAndBlockByNum(seqNum, peerAuthInfo)
   455  
   456  		if err != nil {
   457  			logger.Errorf("cannot read block number %d from ledger, because %+v, skipping...", seqNum, err)
   458  			continue
   459  		}
   460  
   461  		if block == nil {
   462  			logger.Errorf("Wasn't able to read block with sequence number %d from ledger, skipping....", seqNum)
   463  			continue
   464  		}
   465  
   466  		blockBytes, err := pb.Marshal(block)
   467  
   468  		if err != nil {
   469  			logger.Errorf("Could not marshal block: %+v", errors.WithStack(err))
   470  			continue
   471  		}
   472  
   473  		var pvtBytes [][]byte
   474  		if pvtData != nil {
   475  			// Marshal private data
   476  			pvtBytes, err = pvtData.Marshal()
   477  			if err != nil {
   478  				logger.Errorf("Failed to marshal private rwset for block %d due to %+v", seqNum, errors.WithStack(err))
   479  				continue
   480  			}
   481  		}
   482  
   483  		// Appending result to the response
   484  		response.Payloads = append(response.Payloads, &proto.Payload{
   485  			SeqNum:      seqNum,
   486  			Data:        blockBytes,
   487  			PrivateData: pvtBytes,
   488  		})
   489  	}
   490  	// Sending back response with missing blocks
   491  	msg.Respond(&proto.GossipMessage{
   492  		// Copy nonce field from the request, so it will be possible to match response
   493  		Nonce:   msg.GetGossipMessage().Nonce,
   494  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   495  		Channel: []byte(s.chainID),
   496  		Content: &proto.GossipMessage_StateResponse{StateResponse: response},
   497  	})
   498  }
   499  
   500  func (s *GossipStateProviderImpl) handleStateResponse(msg protoext.ReceivedMessage) (uint64, error) {
   501  	max := uint64(0)
   502  	// Send signal that response for given nonce has been received
   503  	response := msg.GetGossipMessage().GetStateResponse()
   504  	// Extract payloads, verify and push into buffer
   505  	if len(response.GetPayloads()) == 0 {
   506  		return uint64(0), errors.New("Received state transfer response without payload")
   507  	}
   508  	for _, payload := range response.GetPayloads() {
   509  		logger.Debugf("Received payload with sequence number %d.", payload.SeqNum)
   510  		block, err := protoutil.UnmarshalBlock(payload.Data)
   511  		if err != nil {
   512  			logger.Warningf("Error unmarshaling payload to block for sequence number %d, due to %+v", payload.SeqNum, err)
   513  			return uint64(0), err
   514  		}
   515  
   516  		if err := s.mediator.VerifyBlock(common2.ChannelID(s.chainID), payload.SeqNum, block); err != nil {
   517  			err = errors.WithStack(err)
   518  			logger.Warningf("Error verifying block with sequence number %d, due to %+v", payload.SeqNum, err)
   519  			return uint64(0), err
   520  		}
   521  		if max < payload.SeqNum {
   522  			max = payload.SeqNum
   523  		}
   524  
   525  		err = s.addPayload(payload, blocking)
   526  		if err != nil {
   527  			logger.Warningf("Block [%d] received from block transfer wasn't added to payload buffer: %v", payload.SeqNum, err)
   528  		}
   529  	}
   530  	return max, nil
   531  }
   532  
   533  // Stop function sends halting signal to all go routines
   534  func (s *GossipStateProviderImpl) Stop() {
   535  	// Make sure stop won't be executed twice
   536  	// and stop channel won't be used again
   537  	s.once.Do(func() {
   538  		close(s.stopCh)
   539  		// Close all resources
   540  		s.ledger.Close()
   541  		close(s.stateRequestCh)
   542  		close(s.stateResponseCh)
   543  	})
   544  }
   545  
   546  func (s *GossipStateProviderImpl) deliverPayloads() {
   547  	for {
   548  		select {
   549  		// Wait for notification that next seq has arrived
   550  		case <-s.payloads.Ready():
   551  			logger.Debugf("[%s] Ready to transfer payloads (blocks) to the ledger, next block number is = [%d]", s.chainID, s.payloads.Next())
   552  			// Collect all subsequent payloads
   553  			for payload := s.payloads.Pop(); payload != nil; payload = s.payloads.Pop() {
   554  				rawBlock := &common.Block{}
   555  				if err := pb.Unmarshal(payload.Data, rawBlock); err != nil {
   556  					logger.Errorf("Error getting block with seqNum = %d due to (%+v)...dropping block", payload.SeqNum, errors.WithStack(err))
   557  					continue
   558  				}
   559  				if rawBlock.Data == nil || rawBlock.Header == nil {
   560  					logger.Errorf("Block with claimed sequence %d has no header (%v) or data (%v)",
   561  						payload.SeqNum, rawBlock.Header, rawBlock.Data)
   562  					continue
   563  				}
   564  				logger.Debugf("[%s] Transferring block [%d] with %d transaction(s) to the ledger", s.chainID, payload.SeqNum, len(rawBlock.Data.Data))
   565  
   566  				// Read all private data into slice
   567  				var p util.PvtDataCollections
   568  				if payload.PrivateData != nil {
   569  					err := p.Unmarshal(payload.PrivateData)
   570  					if err != nil {
   571  						logger.Errorf("Wasn't able to unmarshal private data for block seqNum = %d due to (%+v)...dropping block", payload.SeqNum, errors.WithStack(err))
   572  						continue
   573  					}
   574  				}
   575  				if err := s.commitBlock(rawBlock, p); err != nil {
   576  					if executionErr, isExecutionErr := err.(*vsccErrors.VSCCExecutionFailureError); isExecutionErr {
   577  						logger.Errorf("Failed executing VSCC due to %v. Aborting chain processing", executionErr)
   578  						return
   579  					}
   580  					logger.Panicf("Cannot commit block to the ledger due to %+v", errors.WithStack(err))
   581  				}
   582  			}
   583  		case <-s.stopCh:
   584  			logger.Debug("State provider has been stopped, finishing to push new blocks.")
   585  			return
   586  		}
   587  	}
   588  }
   589  
   590  func (s *GossipStateProviderImpl) antiEntropy() {
   591  	defer logger.Debug("State Provider stopped, stopping anti entropy procedure.")
   592  
   593  	for {
   594  		select {
   595  		case <-s.stopCh:
   596  			return
   597  		case <-time.After(s.config.StateCheckInterval):
   598  			ourHeight, err := s.ledger.LedgerHeight()
   599  			if err != nil {
   600  				// Unable to read from ledger continue to the next round
   601  				logger.Errorf("Cannot obtain ledger height, due to %+v", errors.WithStack(err))
   602  				continue
   603  			}
   604  			if ourHeight == 0 {
   605  				logger.Error("Ledger reported block height of 0 but this should be impossible")
   606  				continue
   607  			}
   608  			maxHeight := s.maxAvailableLedgerHeight()
   609  			if ourHeight >= maxHeight {
   610  				continue
   611  			}
   612  
   613  			s.requestBlocksInRange(uint64(ourHeight), uint64(maxHeight)-1)
   614  		}
   615  	}
   616  }
   617  
   618  // maxAvailableLedgerHeight iterates over all available peers and checks advertised meta state to
   619  // find maximum available ledger height across peers
   620  func (s *GossipStateProviderImpl) maxAvailableLedgerHeight() uint64 {
   621  	max := uint64(0)
   622  	for _, p := range s.mediator.PeersOfChannel(common2.ChannelID(s.chainID)) {
   623  		if p.Properties == nil {
   624  			logger.Debug("Peer", p.PreferredEndpoint(), "doesn't have properties, skipping it")
   625  			continue
   626  		}
   627  		peerHeight := p.Properties.LedgerHeight
   628  		if max < peerHeight {
   629  			max = peerHeight
   630  		}
   631  	}
   632  	return max
   633  }
   634  
   635  // requestBlocksInRange capable to acquire blocks with sequence
   636  // numbers in the range [start...end).
   637  func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) {
   638  	atomic.StoreInt32(&s.stateTransferActive, 1)
   639  	defer atomic.StoreInt32(&s.stateTransferActive, 0)
   640  
   641  	for prev := start; prev <= end; {
   642  		next := min(end, prev+s.config.StateBatchSize)
   643  
   644  		gossipMsg := s.stateRequestMessage(prev, next)
   645  
   646  		responseReceived := false
   647  		tryCounts := 0
   648  
   649  		for !responseReceived {
   650  			if tryCounts > s.config.StateMaxRetries {
   651  				logger.Warningf("Wasn't  able to get blocks in range [%d...%d), after %d retries",
   652  					prev, next, tryCounts)
   653  				return
   654  			}
   655  			// Select peers to ask for blocks
   656  			peer, err := s.selectPeerToRequestFrom(next)
   657  			if err != nil {
   658  				logger.Warningf("Cannot send state request for blocks in range [%d...%d), due to %+v",
   659  					prev, next, errors.WithStack(err))
   660  				return
   661  			}
   662  
   663  			logger.Debugf("State transfer, with peer %s, requesting blocks in range [%d...%d), "+
   664  				"for chainID %s", peer.Endpoint, prev, next, s.chainID)
   665  
   666  			s.mediator.Send(gossipMsg, peer)
   667  			tryCounts++
   668  
   669  			// Wait until timeout or response arrival
   670  			select {
   671  			case msg, stillOpen := <-s.stateResponseCh:
   672  				if !stillOpen {
   673  					return
   674  				}
   675  				if msg.GetGossipMessage().Nonce !=
   676  					gossipMsg.Nonce {
   677  					continue
   678  				}
   679  				// Got corresponding response for state request, can continue
   680  				index, err := s.handleStateResponse(msg)
   681  				if err != nil {
   682  					logger.Warningf("Wasn't able to process state response for "+
   683  						"blocks [%d...%d], due to %+v", prev, next, errors.WithStack(err))
   684  					continue
   685  				}
   686  				prev = index + 1
   687  				responseReceived = true
   688  			case <-time.After(s.config.StateResponseTimeout):
   689  			}
   690  		}
   691  	}
   692  }
   693  
   694  // stateRequestMessage generates state request message for given blocks in range [beginSeq...endSeq]
   695  func (s *GossipStateProviderImpl) stateRequestMessage(beginSeq uint64, endSeq uint64) *proto.GossipMessage {
   696  	return &proto.GossipMessage{
   697  		Nonce:   util.RandomUInt64(),
   698  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   699  		Channel: []byte(s.chainID),
   700  		Content: &proto.GossipMessage_StateRequest{
   701  			StateRequest: &proto.RemoteStateRequest{
   702  				StartSeqNum: beginSeq,
   703  				EndSeqNum:   endSeq,
   704  			},
   705  		},
   706  	}
   707  }
   708  
   709  // selectPeerToRequestFrom selects peer which has required blocks to ask missing blocks from
   710  func (s *GossipStateProviderImpl) selectPeerToRequestFrom(height uint64) (*comm.RemotePeer, error) {
   711  	// Filter peers which posses required range of missing blocks
   712  	peers := s.filterPeers(s.hasRequiredHeight(height))
   713  
   714  	n := len(peers)
   715  	if n == 0 {
   716  		return nil, errors.New("there are no peers to ask for missing blocks from")
   717  	}
   718  
   719  	// Select peer to ask for blocks
   720  	return peers[util.RandomInt(n)], nil
   721  }
   722  
   723  // filterPeers returns list of peers which aligns the predicate provided
   724  func (s *GossipStateProviderImpl) filterPeers(predicate func(peer discovery.NetworkMember) bool) []*comm.RemotePeer {
   725  	var peers []*comm.RemotePeer
   726  
   727  	for _, member := range s.mediator.PeersOfChannel(common2.ChannelID(s.chainID)) {
   728  		if predicate(member) {
   729  			peers = append(peers, &comm.RemotePeer{Endpoint: member.PreferredEndpoint(), PKIID: member.PKIid})
   730  		}
   731  	}
   732  
   733  	return peers
   734  }
   735  
   736  // hasRequiredHeight returns predicate which is capable to filter peers with ledger height above than indicated
   737  // by provided input parameter
   738  func (s *GossipStateProviderImpl) hasRequiredHeight(height uint64) func(peer discovery.NetworkMember) bool {
   739  	return func(peer discovery.NetworkMember) bool {
   740  		if peer.Properties != nil {
   741  			return peer.Properties.LedgerHeight >= height
   742  		}
   743  		logger.Debug(peer.PreferredEndpoint(), "doesn't have properties")
   744  		return false
   745  	}
   746  }
   747  
   748  // AddPayload adds new payload into state.
   749  func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error {
   750  	return s.addPayload(payload, s.blockingMode)
   751  }
   752  
   753  // addPayload adds new payload into state. It may (or may not) block according to the
   754  // given parameter. If it gets a block while in blocking mode - it would wait until
   755  // the block is sent into the payloads buffer.
   756  // Else - it may drop the block, if the payload buffer is too full.
   757  func (s *GossipStateProviderImpl) addPayload(payload *proto.Payload, blockingMode bool) error {
   758  	if payload == nil {
   759  		return errors.New("Given payload is nil")
   760  	}
   761  	logger.Debugf("[%s] Adding payload to local buffer, blockNum = [%d]", s.chainID, payload.SeqNum)
   762  	height, err := s.ledger.LedgerHeight()
   763  	if err != nil {
   764  		return errors.Wrap(err, "Failed obtaining ledger height")
   765  	}
   766  
   767  	if !blockingMode && payload.SeqNum-height >= uint64(s.config.StateBlockBufferSize) {
   768  		return errors.Errorf("Ledger height is at %d, cannot enqueue block with sequence of %d", height, payload.SeqNum)
   769  	}
   770  
   771  	for blockingMode && s.payloads.Size() > s.config.StateBlockBufferSize*2 {
   772  		time.Sleep(enqueueRetryInterval)
   773  	}
   774  
   775  	s.payloads.Push(payload)
   776  	logger.Debugf("Blocks payloads buffer size for channel [%s] is %d blocks", s.chainID, s.payloads.Size())
   777  	return nil
   778  }
   779  
   780  func (s *GossipStateProviderImpl) commitBlock(block *common.Block, pvtData util.PvtDataCollections) error {
   781  
   782  	t1 := time.Now()
   783  
   784  	// Commit block with available private transactions
   785  	if err := s.ledger.StoreBlock(block, pvtData); err != nil {
   786  		logger.Errorf("Got error while committing(%+v)", errors.WithStack(err))
   787  		return err
   788  	}
   789  
   790  	sinceT1 := time.Since(t1)
   791  	s.stateMetrics.CommitDuration.With("channel", s.chainID).Observe(sinceT1.Seconds())
   792  
   793  	// Update ledger height
   794  	s.mediator.UpdateLedgerHeight(block.Header.Number+1, common2.ChannelID(s.chainID))
   795  	logger.Debugf("[%s] Committed block [%d] with %d transaction(s)",
   796  		s.chainID, block.Header.Number, len(block.Data.Data))
   797  
   798  	s.stateMetrics.Height.With("channel", s.chainID).Set(float64(block.Header.Number + 1))
   799  
   800  	return nil
   801  }
   802  
   803  func min(a uint64, b uint64) uint64 {
   804  	return b ^ ((a ^ b) & (-(uint64(a-b) >> 63)))
   805  }