github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/backlog.go (about)

     1  // Copyright 2017 AMIS Technologies
     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/podc"
    21  	"gopkg.in/karalabe/cookiejar.v2/collections/prque"
    22  )
    23  
    24  var (
    25  	// msgPriority is defined for calculating processing priority to speedup consensus
    26  	// msgPreprepare > msgCommit > msgDSelect
    27  	msgPriority = map[uint64]int{
    28  		msgPreprepare: 1,
    29  		msgCommit:     2,
    30  		msgDSelect:    3,
    31  		//msgDSelect:    3,
    32  
    33  	}
    34  )
    35  
    36  // checkMessage checks the message state
    37  // return errInvalidMessage if the message is invalid
    38  // return errFutureMessage if the message view is larger than current view
    39  // return errOldMessage if the message view is smaller than current view
    40  func (c *core) checkMessage(msgCode uint64, view *podc.View) error {
    41  	if view == nil || view.Sequence == nil || view.Round == nil {
    42  		return errInvalidMessage
    43  	}
    44  
    45  	if view.Cmp(c.currentView()) > 0 {
    46  		return errFutureMessage
    47  	}
    48  
    49  	if view.Cmp(c.currentView()) < 0 {
    50  		return errOldMessage
    51  	}
    52  
    53  	if c.waitingForRoundChange {
    54  		return errFutureMessage
    55  	}
    56  
    57  	// StateAcceptRequest only accepts msgPreprepare
    58  	// other messages are future messages
    59  	if c.state == StateAcceptRequest {
    60  		if msgCode > msgPreprepare {
    61  			return errFutureMessage
    62  		}
    63  		return nil
    64  	}
    65  
    66  	// For states(StatePreprepared, StatePrepared, StateCommitted),
    67  	// can accept all message types if processing with same view
    68  	return nil
    69  }
    70  
    71  func (c *core) storeBacklog(msg *message, src podc.Validator) {
    72  	logger := c.logger.New("from", src, "state", c.state)
    73  
    74  	if src.Address() == c.Address() {
    75  		logger.Warn("Backlog from self")
    76  		return
    77  	}
    78  
    79  	logger.Trace("Store future message")
    80  
    81  	c.backlogsMu.Lock()
    82  	defer c.backlogsMu.Unlock()
    83  
    84  	backlog := c.backlogs[src]
    85  	if backlog == nil {
    86  		backlog = prque.New()
    87  	}
    88  	switch msg.Code {
    89  	case msgPreprepare:
    90  		var p *podc.Preprepare
    91  		err := msg.Decode(&p)
    92  		if err == nil {
    93  			backlog.Push(msg, toPriority(msg.Code, p.View))
    94  		}
    95  		// for istanbul.msgDSelect and istanbul.MsgCommit cases
    96  	default:
    97  		var p *podc.Subject
    98  		err := msg.Decode(&p)
    99  		if err == nil {
   100  			backlog.Push(msg, toPriority(msg.Code, p.View))
   101  		}
   102  	}
   103  	c.backlogs[src] = backlog
   104  }
   105  
   106  func (c *core) processBacklog() {
   107  	c.backlogsMu.Lock()
   108  	defer c.backlogsMu.Unlock()
   109  
   110  	for src, backlog := range c.backlogs {
   111  		if backlog == nil {
   112  			continue
   113  		}
   114  
   115  		logger := c.logger.New("from", src, "state", c.state)
   116  		isFuture := false
   117  
   118  		// We stop processing if
   119  		//   1. backlog is empty
   120  		//   2. The first message in queue is a future message
   121  		for !(backlog.Empty() || isFuture) {
   122  			m, prio := backlog.Pop()
   123  			msg := m.(*message)
   124  			var view *podc.View
   125  			switch msg.Code {
   126  			case msgPreprepare:  //?
   127  				//msgDSelect and msgDCommit 구현
   128  			case 	msgDSelect:
   129  			case 	msgCommit:
   130  			//코디와 주고 받는것,
   131  			case 	msgCoordinatorDecide:  //1. 코디 결정
   132  			case 	msgRacing:             //2. 레이싱
   133  			case 	msgCandidateDecide:    //3. 후보군 결정
   134  
   135  
   136  			//case 	msgRoundChange:
   137  			//Qmanager와 주고 받는 것 :
   138  			case 	msgHandleQman:
   139  			//case 	msgExtraDataRequest:
   140  			//case 	msgExtraDataSend:
   141  			//case 	msgCoordinatorConfirmRequest:
   142  			//case 	msgCoordinatorConfirmSend:
   143  
   144  				var m *podc.Preprepare
   145  				err := msg.Decode(&m)
   146  				if err == nil {
   147  					view = m.View   //메시지뷰를 뷰에 설
   148  				}
   149  			default:
   150  				var sub *podc.Subject
   151  				err := msg.Decode(&sub)
   152  				if err == nil {
   153  					view = sub.View //주제 뷰를 설정
   154  				}
   155  			}
   156  			if view == nil {
   157  				logger.Debug("Nil view", "msg", msg)
   158  				continue
   159  			}
   160  			// Push back if it's a future message
   161  			err := c.checkMessage(msg.Code, view)
   162  			if err != nil {
   163  				if err == errFutureMessage {
   164  					logger.Trace("Stop processing backlog", "msg", msg)
   165  					backlog.Push(msg, prio)
   166  					isFuture = true
   167  					break
   168  				}
   169  				logger.Trace("Skip the backlog event", "msg", msg, "err", err)
   170  				continue
   171  			}
   172  			logger.Trace("Post backlog event", "msg", msg)
   173  
   174  			go c.sendEvent(backlogEvent{
   175  				src: src,
   176  				msg: msg,
   177  			})
   178  		}
   179  	}
   180  }
   181  
   182  func toPriority(msgCode uint64, view *podc.View) float32 {  //나중에 시퀀스,, 중요. 속도 계산해서,, 추후 처리할 것.
   183  	// FIXME: round will be reset as 0 while new sequence
   184  	// 10 * Round limits the range of message code is from 0 to 9
   185  	// 1000 * Sequence limits the range of round is from 0 to 99
   186  	return -float32(view.Sequence.Uint64()*1000 + view.Round.Uint64()*10 + uint64(msgPriority[msgCode]))
   187  }