github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/consensus/istanbul/ibft/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/kisexp/xdchain/consensus/istanbul"
    21  	istanbulcommon "github.com/kisexp/xdchain/consensus/istanbul/common"
    22  	ibfttypes "github.com/kisexp/xdchain/consensus/istanbul/ibft/types"
    23  )
    24  
    25  func (c *core) handleRequest(request *istanbul.Request) error {
    26  	logger := c.logger.New("state", c.state, "seq", c.current.sequence)
    27  	if err := c.checkRequestMsg(request); err != nil {
    28  		if err == istanbulcommon.ErrInvalidMessage {
    29  			logger.Warn("invalid request")
    30  			return err
    31  		}
    32  		logger.Warn("unexpected request", "err", err, "number", request.Proposal.Number(), "hash", request.Proposal.Hash())
    33  		return err
    34  	}
    35  	logger.Trace("handleRequest", "number", request.Proposal.Number(), "hash", request.Proposal.Hash())
    36  
    37  	c.current.pendingRequest = request
    38  	if c.state == ibfttypes.StateAcceptRequest {
    39  		c.sendPreprepare(request)
    40  	}
    41  	return nil
    42  }
    43  
    44  // check request state
    45  // return errInvalidMessage if the message is invalid
    46  // return errFutureMessage if the sequence of proposal is larger than current sequence
    47  // return errOldMessage if the sequence of proposal is smaller than current sequence
    48  func (c *core) checkRequestMsg(request *istanbul.Request) error {
    49  	if request == nil || request.Proposal == nil {
    50  		return istanbulcommon.ErrInvalidMessage
    51  	}
    52  
    53  	if c := c.current.sequence.Cmp(request.Proposal.Number()); c > 0 {
    54  		return istanbulcommon.ErrOldMessage
    55  	} else if c < 0 {
    56  		return istanbulcommon.ErrFutureMessage
    57  	} else {
    58  		return nil
    59  	}
    60  }
    61  
    62  func (c *core) storeRequestMsg(request *istanbul.Request) {
    63  	logger := c.logger.New("state", c.state)
    64  
    65  	logger.Trace("Store future request", "number", request.Proposal.Number(), "hash", request.Proposal.Hash())
    66  
    67  	c.pendingRequestsMu.Lock()
    68  	defer c.pendingRequestsMu.Unlock()
    69  
    70  	c.pendingRequests.Push(request, float32(-request.Proposal.Number().Int64()))
    71  }
    72  
    73  func (c *core) processPendingRequests() {
    74  	c.pendingRequestsMu.Lock()
    75  	defer c.pendingRequestsMu.Unlock()
    76  
    77  	for !(c.pendingRequests.Empty()) {
    78  		m, prio := c.pendingRequests.Pop()
    79  		r, ok := m.(*istanbul.Request)
    80  		if !ok {
    81  			c.logger.Warn("Malformed request, skip", "msg", m)
    82  			continue
    83  		}
    84  		// Push back if it's a future message
    85  		err := c.checkRequestMsg(r)
    86  		if err != nil {
    87  			if err == istanbulcommon.ErrFutureMessage {
    88  				c.logger.Trace("Stop processing request", "number", r.Proposal.Number(), "hash", r.Proposal.Hash())
    89  				c.pendingRequests.Push(m, prio)
    90  				break
    91  			}
    92  			c.logger.Trace("Skip the pending request", "number", r.Proposal.Number(), "hash", r.Proposal.Hash(), "err", err)
    93  			continue
    94  		}
    95  		c.logger.Trace("Post pending request", "number", r.Proposal.Number(), "hash", r.Proposal.Hash())
    96  
    97  		go c.sendEvent(istanbul.RequestEvent{
    98  			Proposal: r.Proposal,
    99  		})
   100  	}
   101  }