github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/state/state.go (about)

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