github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/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  	"errors"
    12  	"fmt"
    13  	"sync"
    14  	"sync/atomic"
    15  	"time"
    16  
    17  	pb "github.com/golang/protobuf/proto"
    18  	"github.com/hyperledger/fabric/core/committer"
    19  	"github.com/hyperledger/fabric/gossip/api"
    20  	"github.com/hyperledger/fabric/gossip/comm"
    21  	common2 "github.com/hyperledger/fabric/gossip/common"
    22  	"github.com/hyperledger/fabric/gossip/discovery"
    23  	"github.com/hyperledger/fabric/gossip/util"
    24  	"github.com/hyperledger/fabric/protos/common"
    25  	proto "github.com/hyperledger/fabric/protos/gossip"
    26  	"github.com/op/go-logging"
    27  )
    28  
    29  // GossipStateProvider is the interface to acquire sequences of the ledger blocks
    30  // capable to full fill missing blocks by running state replication and
    31  // sending request to get missing block to other nodes
    32  type GossipStateProvider interface {
    33  	// Retrieve block with sequence number equal to index
    34  	GetBlock(index uint64) *common.Block
    35  
    36  	AddPayload(payload *proto.Payload) error
    37  
    38  	// Stop terminates state transfer object
    39  	Stop()
    40  }
    41  
    42  const (
    43  	defAntiEntropyInterval             = 10 * time.Second
    44  	defAntiEntropyStateResponseTimeout = 3 * time.Second
    45  	defAntiEntropyBatchSize            = 10
    46  
    47  	defChannelBufferSize     = 100
    48  	defAntiEntropyMaxRetries = 3
    49  
    50  	defMaxBlockDistance = 100
    51  )
    52  
    53  // GossipAdapter defines gossip/communication required interface for state provider
    54  type GossipAdapter interface {
    55  	// Send sends a message to remote peers
    56  	Send(msg *proto.GossipMessage, peers ...*comm.RemotePeer)
    57  
    58  	// Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate.
    59  	// If passThrough is false, the messages are processed by the gossip layer beforehand.
    60  	// If passThrough is true, the gossip layer doesn't intervene and the messages
    61  	// can be used to send a reply back to the sender
    62  	Accept(acceptor common2.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage)
    63  
    64  	// UpdateChannelMetadata updates the self metadata the peer
    65  	// publishes to other peers about its channel-related state
    66  	UpdateChannelMetadata(metadata []byte, chainID common2.ChainID)
    67  
    68  	// PeersOfChannel returns the NetworkMembers considered alive
    69  	// and also subscribed to the channel given
    70  	PeersOfChannel(common2.ChainID) []discovery.NetworkMember
    71  }
    72  
    73  // GossipStateProviderImpl the implementation of the GossipStateProvider interface
    74  // the struct to handle in memory sliding window of
    75  // new ledger block to be acquired by hyper ledger
    76  type GossipStateProviderImpl struct {
    77  	// MessageCryptoService
    78  	mcs api.MessageCryptoService
    79  
    80  	// Chain id
    81  	chainID string
    82  
    83  	// The gossiping service
    84  	gossip GossipAdapter
    85  
    86  	// Channel to read gossip messages from
    87  	gossipChan <-chan *proto.GossipMessage
    88  
    89  	commChan <-chan proto.ReceivedMessage
    90  
    91  	// Queue of payloads which wasn't acquired yet
    92  	payloads PayloadsBuffer
    93  
    94  	committer committer.Committer
    95  
    96  	stateResponseCh chan proto.ReceivedMessage
    97  
    98  	stateRequestCh chan proto.ReceivedMessage
    99  
   100  	stopCh chan struct{}
   101  
   102  	done sync.WaitGroup
   103  
   104  	once sync.Once
   105  
   106  	stateTransferActive int32
   107  }
   108  
   109  var logger *logging.Logger // package-level logger
   110  
   111  func init() {
   112  	logger = util.GetLogger(util.LoggingStateModule, "")
   113  }
   114  
   115  // NewGossipStateProvider creates initialized instance of gossip state provider
   116  func NewGossipStateProvider(chainID string, g GossipAdapter, committer committer.Committer, mcs api.MessageCryptoService) GossipStateProvider {
   117  	logger := util.GetLogger(util.LoggingStateModule, "")
   118  
   119  	gossipChan, _ := g.Accept(func(message interface{}) bool {
   120  		// Get only data messages
   121  		return message.(*proto.GossipMessage).IsDataMsg() &&
   122  			bytes.Equal(message.(*proto.GossipMessage).Channel, []byte(chainID))
   123  	}, false)
   124  
   125  	remoteStateMsgFilter := func(message interface{}) bool {
   126  		receivedMsg := message.(proto.ReceivedMessage)
   127  		msg := receivedMsg.GetGossipMessage()
   128  		if !msg.IsRemoteStateMessage() {
   129  			return false
   130  		}
   131  		// If we're not running with authentication, no point
   132  		// in enforcing access control
   133  		if !receivedMsg.GetConnectionInfo().IsAuthenticated() {
   134  			return true
   135  		}
   136  		connInfo := receivedMsg.GetConnectionInfo()
   137  		authErr := mcs.VerifyByChannel(msg.Channel, connInfo.Identity, connInfo.Auth.Signature, connInfo.Auth.SignedData)
   138  		if authErr != nil {
   139  			logger.Warning("Got unauthorized nodeMetastate transfer request from", string(connInfo.Identity))
   140  			return false
   141  		}
   142  		return true
   143  	}
   144  
   145  	// Filter message which are only relevant for nodeMetastate transfer
   146  	_, commChan := g.Accept(remoteStateMsgFilter, true)
   147  
   148  	height, err := committer.LedgerHeight()
   149  	if height == 0 {
   150  		// Panic here since this is an indication of invalid situation which should not happen in normal
   151  		// code path.
   152  		logger.Panic("Committer height cannot be zero, ledger should include at least one block (genesis).")
   153  	}
   154  
   155  	if err != nil {
   156  		logger.Error("Could not read ledger info to obtain current ledger height due to: ", err)
   157  		// Exiting as without ledger it will be impossible
   158  		// to deliver new blocks
   159  		return nil
   160  	}
   161  
   162  	s := &GossipStateProviderImpl{
   163  		// MessageCryptoService
   164  		mcs: mcs,
   165  
   166  		// Chain ID
   167  		chainID: chainID,
   168  
   169  		// Instance of the gossip
   170  		gossip: g,
   171  
   172  		// Channel to read new messages from
   173  		gossipChan: gossipChan,
   174  
   175  		// Channel to read direct messages from other peers
   176  		commChan: commChan,
   177  
   178  		// Create a queue for payload received
   179  		payloads: NewPayloadsBuffer(height),
   180  
   181  		committer: committer,
   182  
   183  		stateResponseCh: make(chan proto.ReceivedMessage, defChannelBufferSize),
   184  
   185  		stateRequestCh: make(chan proto.ReceivedMessage, defChannelBufferSize),
   186  
   187  		stopCh: make(chan struct{}, 1),
   188  
   189  		stateTransferActive: 0,
   190  
   191  		once: sync.Once{},
   192  	}
   193  
   194  	nodeMetastate := NewNodeMetastate(height - 1)
   195  
   196  	logger.Infof("Updating node metadata information, "+
   197  		"current ledger sequence is at = %d, next expected block is = %d", nodeMetastate.LedgerHeight, s.payloads.Next())
   198  
   199  	b, err := nodeMetastate.Bytes()
   200  	if err == nil {
   201  		logger.Debug("Updating gossip metadate nodeMetastate", nodeMetastate)
   202  		g.UpdateChannelMetadata(b, common2.ChainID(s.chainID))
   203  	} else {
   204  		logger.Errorf("Unable to serialize node meta nodeMetastate, error = %s", err)
   205  	}
   206  
   207  	s.done.Add(4)
   208  
   209  	// Listen for incoming communication
   210  	go s.listen()
   211  	// Deliver in order messages into the incoming channel
   212  	go s.deliverPayloads()
   213  	// Execute anti entropy to fill missing gaps
   214  	go s.antiEntropy()
   215  	// Taking care of state request messages
   216  	go s.processStateRequests()
   217  
   218  	return s
   219  }
   220  
   221  func (s *GossipStateProviderImpl) listen() {
   222  	defer s.done.Done()
   223  
   224  	for {
   225  		select {
   226  		case msg := <-s.gossipChan:
   227  			logger.Debug("Received new message via gossip channel")
   228  			go s.queueNewMessage(msg)
   229  		case msg := <-s.commChan:
   230  			logger.Debug("Direct message ", msg)
   231  			go s.directMessage(msg)
   232  		case <-s.stopCh:
   233  			s.stopCh <- struct{}{}
   234  			logger.Debug("Stop listening for new messages")
   235  			return
   236  		}
   237  	}
   238  }
   239  
   240  func (s *GossipStateProviderImpl) directMessage(msg proto.ReceivedMessage) {
   241  	logger.Debug("[ENTER] -> directMessage")
   242  	defer logger.Debug("[EXIT] ->  directMessage")
   243  
   244  	if msg == nil {
   245  		logger.Error("Got nil message via end-to-end channel, should not happen!")
   246  		return
   247  	}
   248  
   249  	if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
   250  		logger.Warning("Received state transfer request for channel",
   251  			string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
   252  		return
   253  	}
   254  
   255  	incoming := msg.GetGossipMessage()
   256  
   257  	if incoming.GetStateRequest() != nil {
   258  		if len(s.stateRequestCh) < defChannelBufferSize {
   259  			// Forward state request to the channel, if there are too
   260  			// many message of state request ignore to avoid flooding.
   261  			s.stateRequestCh <- msg
   262  		}
   263  	} else if incoming.GetStateResponse() != nil {
   264  		// If no state transfer procedure activate there is
   265  		// no reason to process the message
   266  		if atomic.LoadInt32(&s.stateTransferActive) == 1 {
   267  			// Send signal of state response message
   268  			s.stateResponseCh <- msg
   269  		}
   270  	}
   271  }
   272  
   273  func (s *GossipStateProviderImpl) processStateRequests() {
   274  	defer s.done.Done()
   275  
   276  	for {
   277  		select {
   278  		case msg := <-s.stateRequestCh:
   279  			s.handleStateRequest(msg)
   280  		case <-s.stopCh:
   281  			s.stopCh <- struct{}{}
   282  			return
   283  		}
   284  	}
   285  }
   286  
   287  // Handle state request message, validate batch size, read current leader state to
   288  // obtain required blocks, build response message and send it back
   289  func (s *GossipStateProviderImpl) handleStateRequest(msg proto.ReceivedMessage) {
   290  	if msg == nil {
   291  		return
   292  	}
   293  	request := msg.GetGossipMessage().GetStateRequest()
   294  
   295  	batchSize := request.EndSeqNum - request.StartSeqNum
   296  	if batchSize > defAntiEntropyBatchSize {
   297  		logger.Errorf("Requesting blocks batchSize size (%d) greater than configured allowed"+
   298  			" (%d) batching for anti-entropy. Ignoring request...", batchSize, defAntiEntropyBatchSize)
   299  		return
   300  	}
   301  
   302  	if request.StartSeqNum > request.EndSeqNum {
   303  		logger.Errorf("Invalid sequence interval [%d...%d], ignoring request...", request.StartSeqNum, request.EndSeqNum)
   304  		return
   305  	}
   306  
   307  	currentHeight, err := s.committer.LedgerHeight()
   308  	if err != nil {
   309  		logger.Errorf("Cannot access to current ledger height, due to %s", err)
   310  		return
   311  	}
   312  	if currentHeight < request.EndSeqNum {
   313  		logger.Warningf("Received state request to transfer blocks with sequence numbers higher  [%d...%d] "+
   314  			"than available in ledger (%d)", request.StartSeqNum, request.StartSeqNum, currentHeight)
   315  	}
   316  
   317  	endSeqNum := min(currentHeight, request.EndSeqNum)
   318  
   319  	response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)}
   320  	for seqNum := request.StartSeqNum; seqNum <= endSeqNum; seqNum++ {
   321  		logger.Debug("Reading block ", seqNum, " from the committer service")
   322  		blocks := s.committer.GetBlocks([]uint64{seqNum})
   323  
   324  		if len(blocks) == 0 {
   325  			logger.Errorf("Wasn't able to read block with sequence number %d from ledger, skipping....", seqNum)
   326  			continue
   327  		}
   328  
   329  		blockBytes, err := pb.Marshal(blocks[0])
   330  		if err != nil {
   331  			logger.Errorf("Could not marshal block: %s", err)
   332  		}
   333  
   334  		response.Payloads = append(response.Payloads, &proto.Payload{
   335  			SeqNum: seqNum,
   336  			Data:   blockBytes,
   337  		})
   338  	}
   339  	// Sending back response with missing blocks
   340  	msg.Respond(&proto.GossipMessage{
   341  		// Copy nonce field from the request, so it will be possible to match response
   342  		Nonce:   msg.GetGossipMessage().Nonce,
   343  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   344  		Channel: []byte(s.chainID),
   345  		Content: &proto.GossipMessage_StateResponse{response},
   346  	})
   347  }
   348  
   349  func (s *GossipStateProviderImpl) handleStateResponse(msg proto.ReceivedMessage) (uint64, error) {
   350  	max := uint64(0)
   351  	// Send signal that response for given nonce has been received
   352  	response := msg.GetGossipMessage().GetStateResponse()
   353  	// Extract payloads, verify and push into buffer
   354  	if len(response.GetPayloads()) == 0 {
   355  		return uint64(0), errors.New("Received state tranfer response without payload")
   356  	}
   357  	for _, payload := range response.GetPayloads() {
   358  		logger.Debugf("Received payload with sequence number %d.", payload.SeqNum)
   359  		if err := s.mcs.VerifyBlock(common2.ChainID(s.chainID), payload.SeqNum, payload.Data); err != nil {
   360  			logger.Warningf("Error verifying block with sequence number %d, due to %s", payload.SeqNum, err)
   361  			return uint64(0), err
   362  		}
   363  		if max < payload.SeqNum {
   364  			max = payload.SeqNum
   365  		}
   366  		err := s.payloads.Push(payload)
   367  		if err != nil {
   368  			logger.Warningf("Payload with sequence number %d was received earlier", payload.SeqNum)
   369  		}
   370  	}
   371  	return max, nil
   372  }
   373  
   374  // Stop function send halting signal to all go routines
   375  func (s *GossipStateProviderImpl) Stop() {
   376  	// Make sure stop won't be executed twice
   377  	// and stop channel won't be used again
   378  	s.once.Do(func() {
   379  		s.stopCh <- struct{}{}
   380  		// Make sure all go-routines has finished
   381  		s.done.Wait()
   382  		// Close all resources
   383  		s.committer.Close()
   384  		close(s.stateRequestCh)
   385  		close(s.stateResponseCh)
   386  		close(s.stopCh)
   387  	})
   388  }
   389  
   390  // New message notification/handler
   391  func (s *GossipStateProviderImpl) queueNewMessage(msg *proto.GossipMessage) {
   392  	if !bytes.Equal(msg.Channel, []byte(s.chainID)) {
   393  		logger.Warning("Received enqueue for channel",
   394  			string(msg.Channel), "while expecting channel", s.chainID, "ignoring enqueue")
   395  		return
   396  	}
   397  
   398  	dataMsg := msg.GetDataMsg()
   399  	if dataMsg != nil {
   400  		if err := s.AddPayload(dataMsg.GetPayload()); err != nil {
   401  			logger.Warning("Failed adding payload:", err)
   402  			return
   403  		}
   404  		logger.Debugf("Received new payload with sequence number = [%d]", dataMsg.Payload.SeqNum)
   405  	} else {
   406  		logger.Debug("Gossip message received is not of data message type, usually this should not happen.")
   407  	}
   408  }
   409  
   410  func (s *GossipStateProviderImpl) deliverPayloads() {
   411  	defer s.done.Done()
   412  
   413  	for {
   414  		select {
   415  		// Wait for notification that next seq has arrived
   416  		case <-s.payloads.Ready():
   417  			logger.Debugf("Ready to transfer payloads to the ledger, next sequence number is = [%d]", s.payloads.Next())
   418  			// Collect all subsequent payloads
   419  			for payload := s.payloads.Pop(); payload != nil; payload = s.payloads.Pop() {
   420  				rawBlock := &common.Block{}
   421  				if err := pb.Unmarshal(payload.Data, rawBlock); err != nil {
   422  					logger.Errorf("Error getting block with seqNum = %d due to (%s)...dropping block", payload.SeqNum, err)
   423  					continue
   424  				}
   425  				if rawBlock.Data == nil || rawBlock.Header == nil {
   426  					logger.Errorf("Block with claimed sequence %d has no header (%v) or data (%v)",
   427  						payload.SeqNum, rawBlock.Header, rawBlock.Data)
   428  					continue
   429  				}
   430  				logger.Debug("New block with claimed sequence number ", payload.SeqNum, " transactions num ", len(rawBlock.Data.Data))
   431  				s.commitBlock(rawBlock)
   432  			}
   433  		case <-s.stopCh:
   434  			s.stopCh <- struct{}{}
   435  			logger.Debug("State provider has been stoped, finishing to push new blocks.")
   436  			return
   437  		}
   438  	}
   439  }
   440  
   441  func (s *GossipStateProviderImpl) antiEntropy() {
   442  	defer s.done.Done()
   443  	defer logger.Debug("State Provider stopped, stopping anti entropy procedure.")
   444  
   445  	for {
   446  		select {
   447  		case <-s.stopCh:
   448  			s.stopCh <- struct{}{}
   449  			return
   450  		case <-time.After(defAntiEntropyInterval):
   451  			current, err := s.committer.LedgerHeight()
   452  			if err != nil {
   453  				// Unable to read from ledger continue to the next round
   454  				logger.Error("Cannot obtain ledger height, due to", err)
   455  				continue
   456  			}
   457  			if current == 0 {
   458  				logger.Error("Ledger reported block height of 0 but this should be impossible")
   459  				continue
   460  			}
   461  			max := s.maxAvailableLedgerHeight()
   462  
   463  			if current-1 >= max {
   464  				continue
   465  			}
   466  
   467  			s.requestBlocksInRange(uint64(current), uint64(max))
   468  		}
   469  	}
   470  }
   471  
   472  // Iterate over all available peers and check advertised meta state to
   473  // find maximum available ledger height across peers
   474  func (s *GossipStateProviderImpl) maxAvailableLedgerHeight() uint64 {
   475  	max := uint64(0)
   476  	for _, p := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) {
   477  		if nodeMetastate, err := FromBytes(p.Metadata); err == nil {
   478  			if max < nodeMetastate.LedgerHeight {
   479  				max = nodeMetastate.LedgerHeight
   480  			}
   481  		}
   482  	}
   483  	return max
   484  }
   485  
   486  // GetBlocksInRange capable to acquire blocks with sequence
   487  // numbers in the range [start...end].
   488  func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) {
   489  	atomic.StoreInt32(&s.stateTransferActive, 1)
   490  	defer atomic.StoreInt32(&s.stateTransferActive, 0)
   491  
   492  	for prev := start; prev <= end; {
   493  		next := min(end, prev+defAntiEntropyBatchSize)
   494  
   495  		gossipMsg := s.stateRequestMessage(prev, next)
   496  
   497  		responseReceived := false
   498  		tryCounts := 0
   499  
   500  		for !responseReceived {
   501  			if tryCounts > defAntiEntropyMaxRetries {
   502  				logger.Warningf("Wasn't  able to get blocks in range [%d...%d], after %d retries",
   503  					prev, next, tryCounts)
   504  				return
   505  			}
   506  			// Select peers to ask for blocks
   507  			peer, err := s.selectPeerToRequestFrom(next)
   508  			if err != nil {
   509  				logger.Warningf("Cannot send state request for blocks in range [%d...%d], due to",
   510  					prev, next, err)
   511  				return
   512  			}
   513  
   514  			logger.Debugf("State transfer, with peer %s, requesting blocks in range [%d...%d], "+
   515  				"for chainID %s", peer.Endpoint, prev, next, s.chainID)
   516  
   517  			s.gossip.Send(gossipMsg, peer)
   518  			tryCounts++
   519  
   520  			// Wait until timeout or response arrival
   521  			select {
   522  			case msg := <-s.stateResponseCh:
   523  				if msg.GetGossipMessage().Nonce != gossipMsg.Nonce {
   524  					continue
   525  				}
   526  				// Got corresponding response for state request, can continue
   527  				index, err := s.handleStateResponse(msg)
   528  				if err != nil {
   529  					logger.Warningf("Wasn't able to process state response for "+
   530  						"blocks [%d...%d], due to %s", prev, next, err)
   531  					continue
   532  				}
   533  				prev = index + 1
   534  				responseReceived = true
   535  			case <-time.After(defAntiEntropyStateResponseTimeout):
   536  			case <-s.stopCh:
   537  				s.stopCh <- struct{}{}
   538  				return
   539  			}
   540  		}
   541  	}
   542  }
   543  
   544  // Generate state request message for given blocks in range [beginSeq...endSeq]
   545  func (s *GossipStateProviderImpl) stateRequestMessage(beginSeq uint64, endSeq uint64) *proto.GossipMessage {
   546  	return &proto.GossipMessage{
   547  		Nonce:   util.RandomUInt64(),
   548  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   549  		Channel: []byte(s.chainID),
   550  		Content: &proto.GossipMessage_StateRequest{
   551  			StateRequest: &proto.RemoteStateRequest{
   552  				StartSeqNum: beginSeq,
   553  				EndSeqNum:   endSeq,
   554  			},
   555  		},
   556  	}
   557  }
   558  
   559  // Select peer which has required blocks to ask missing blocks from
   560  func (s *GossipStateProviderImpl) selectPeerToRequestFrom(height uint64) (*comm.RemotePeer, error) {
   561  	// Filter peers which posses required range of missing blocks
   562  	peers := s.filterPeers(s.hasRequiredHeight(height))
   563  
   564  	n := len(peers)
   565  	if n == 0 {
   566  		return nil, errors.New("there are no peers to ask for missing blocks from")
   567  	}
   568  
   569  	// Select peers to ask for blocks
   570  	return peers[util.RandomInt(n)], nil
   571  }
   572  
   573  // filterPeers return list of peers which aligns the predicate provided
   574  func (s *GossipStateProviderImpl) filterPeers(predicate func(peer discovery.NetworkMember) bool) []*comm.RemotePeer {
   575  	var peers []*comm.RemotePeer
   576  
   577  	for _, member := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) {
   578  		if predicate(member) {
   579  			peers = append(peers, &comm.RemotePeer{Endpoint: member.PreferredEndpoint(), PKIID: member.PKIid})
   580  		}
   581  	}
   582  
   583  	return peers
   584  }
   585  
   586  // hasRequiredHeight returns predicate which is capable to filter peers with ledger height above than indicated
   587  // by provided input parameter
   588  func (s *GossipStateProviderImpl) hasRequiredHeight(height uint64) func(peer discovery.NetworkMember) bool {
   589  	return func(peer discovery.NetworkMember) bool {
   590  		if nodeMetadata, err := FromBytes(peer.Metadata); err != nil {
   591  			logger.Errorf("Unable to de-serialize node meta state, error = %s", err)
   592  		} else if nodeMetadata.LedgerHeight >= height {
   593  			return true
   594  		}
   595  
   596  		return false
   597  	}
   598  }
   599  
   600  // GetBlock return ledger block given its sequence number as a parameter
   601  func (s *GossipStateProviderImpl) GetBlock(index uint64) *common.Block {
   602  	// Try to read missing block from the ledger, should return no nil with
   603  	// content including at least one block
   604  	if blocks := s.committer.GetBlocks([]uint64{index}); blocks != nil && len(blocks) > 0 {
   605  		return blocks[0]
   606  	}
   607  
   608  	return nil
   609  }
   610  
   611  // AddPayload add new payload into state
   612  func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error {
   613  	if payload == nil {
   614  		return errors.New("Given payload is nil")
   615  	}
   616  	logger.Debug("Adding new payload into the buffer, seqNum = ", payload.SeqNum)
   617  	height, err := s.committer.LedgerHeight()
   618  	if err != nil {
   619  		return fmt.Errorf("Failed obtaining ledger height: %v", err)
   620  	}
   621  
   622  	if payload.SeqNum-height >= defMaxBlockDistance {
   623  		return fmt.Errorf("Ledger height is at %d, cannot enqueue block with sequence of %d", height, payload.SeqNum)
   624  	}
   625  
   626  	return s.payloads.Push(payload)
   627  }
   628  
   629  func (s *GossipStateProviderImpl) commitBlock(block *common.Block) error {
   630  	if err := s.committer.Commit(block); err != nil {
   631  		logger.Errorf("Got error while committing(%s)", err)
   632  		return err
   633  	}
   634  
   635  	// Update ledger level within node metadata
   636  	nodeMetastate := NewNodeMetastate(block.Header.Number)
   637  	// Decode nodeMetastate to byte array
   638  	b, err := nodeMetastate.Bytes()
   639  	if err == nil {
   640  		s.gossip.UpdateChannelMetadata(b, common2.ChainID(s.chainID))
   641  	} else {
   642  
   643  		logger.Errorf("Unable to serialize node meta nodeMetastate, error = %s", err)
   644  	}
   645  
   646  	logger.Debugf("Channel [%s]: Created block [%d] with %d transaction(s)",
   647  		s.chainID, block.Header.Number, len(block.Data.Data))
   648  
   649  	return nil
   650  }
   651  
   652  func min(a uint64, b uint64) uint64 {
   653  	return b ^ ((a ^ b) & (-(uint64(a-b) >> 63)))
   654  }