github.com/ConsenSys/Quorum@v20.10.0+incompatible/consensus/istanbul/core/request.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    21  )
    22  
    23  func (c *core) handleRequest(request *istanbul.Request) error {
    24  	logger := c.logger.New("state", c.state, "seq", c.current.sequence)
    25  	if err := c.checkRequestMsg(request); err != nil {
    26  		if err == errInvalidMessage {
    27  			logger.Warn("invalid request")
    28  			return err
    29  		}
    30  		logger.Warn("unexpected request", "err", err, "number", request.Proposal.Number(), "hash", request.Proposal.Hash())
    31  		return err
    32  	}
    33  	logger.Trace("handleRequest", "number", request.Proposal.Number(), "hash", request.Proposal.Hash())
    34  
    35  	c.current.pendingRequest = request
    36  	if c.state == StateAcceptRequest {
    37  		c.sendPreprepare(request)
    38  	}
    39  	return nil
    40  }
    41  
    42  // check request state
    43  // return errInvalidMessage if the message is invalid
    44  // return errFutureMessage if the sequence of proposal is larger than current sequence
    45  // return errOldMessage if the sequence of proposal is smaller than current sequence
    46  func (c *core) checkRequestMsg(request *istanbul.Request) error {
    47  	if request == nil || request.Proposal == nil {
    48  		return errInvalidMessage
    49  	}
    50  
    51  	if c := c.current.sequence.Cmp(request.Proposal.Number()); c > 0 {
    52  		return errOldMessage
    53  	} else if c < 0 {
    54  		return errFutureMessage
    55  	} else {
    56  		return nil
    57  	}
    58  }
    59  
    60  func (c *core) storeRequestMsg(request *istanbul.Request) {
    61  	logger := c.logger.New("state", c.state)
    62  
    63  	logger.Trace("Store future request", "number", request.Proposal.Number(), "hash", request.Proposal.Hash())
    64  
    65  	c.pendingRequestsMu.Lock()
    66  	defer c.pendingRequestsMu.Unlock()
    67  
    68  	c.pendingRequests.Push(request, float32(-request.Proposal.Number().Int64()))
    69  }
    70  
    71  func (c *core) processPendingRequests() {
    72  	c.pendingRequestsMu.Lock()
    73  	defer c.pendingRequestsMu.Unlock()
    74  
    75  	for !(c.pendingRequests.Empty()) {
    76  		m, prio := c.pendingRequests.Pop()
    77  		r, ok := m.(*istanbul.Request)
    78  		if !ok {
    79  			c.logger.Warn("Malformed request, skip", "msg", m)
    80  			continue
    81  		}
    82  		// Push back if it's a future message
    83  		err := c.checkRequestMsg(r)
    84  		if err != nil {
    85  			if err == errFutureMessage {
    86  				c.logger.Trace("Stop processing request", "number", r.Proposal.Number(), "hash", r.Proposal.Hash())
    87  				c.pendingRequests.Push(m, prio)
    88  				break
    89  			}
    90  			c.logger.Trace("Skip the pending request", "number", r.Proposal.Number(), "hash", r.Proposal.Hash(), "err", err)
    91  			continue
    92  		}
    93  		c.logger.Trace("Post pending request", "number", r.Proposal.Number(), "hash", r.Proposal.Hash())
    94  
    95  		go c.sendEvent(istanbul.RequestEvent{
    96  			Proposal: r.Proposal,
    97  		})
    98  	}
    99  }