github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/roundchange.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  	"math/big"
    21  	"sync"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/consensus/podc"
    25  )
    26  
    27  // sendNextRoundChange sends the round change message with current round + 1
    28  func (c *core) sendNextRoundChange() {
    29  
    30  	cv := c.currentView()
    31  	c.sendRoundChange(new(big.Int).Add(cv.Round, common.Big1))
    32  
    33  }
    34  
    35  // sendRoundChange sends the round change message with the given round
    36  func (c *core) sendRoundChange(round *big.Int) {
    37  	logger := c.logger.New("state", c.state)
    38  
    39  	cv := c.currentView()
    40  	if cv.Round.Cmp(round) >= 0 {
    41  		logger.Error("Cannot send out the round change", "current round", cv.Round, "target round", round)
    42  		return
    43  	}
    44  
    45  	c.catchUpRound(&podc.View{
    46  		// The round number we'd like to transfer to.
    47  		Round:    new(big.Int).Set(round),
    48  		Sequence: new(big.Int).Set(cv.Sequence),
    49  	})
    50  
    51  	// Now we have the new round number and sequence number
    52  	cv = c.currentView()
    53  	rc := &roundChange{
    54  		Round:    new(big.Int).Set(cv.Round),
    55  		Sequence: new(big.Int).Set(cv.Sequence),
    56  		Digest:   common.Hash{},
    57  	}
    58  
    59  	payload, err := Encode(rc)
    60  	if err != nil {
    61  		logger.Error("Failed to encode round change", "rc", rc, "err", err)
    62  		return
    63  	}
    64  
    65  	c.broadcast(&message{
    66  		Code: msgRoundChange,
    67  		Msg:  payload,
    68  	})
    69  }
    70  
    71  func (c *core) handleRoundChange(msg *message, src podc.Validator) error {
    72  	logger := c.logger.New("state", c.state)
    73  		// Decode round change message
    74  		var rc *roundChange
    75  	//startsync := make (chan int)
    76  	//if( !global.QManConnected) { // if i'm not Qman and general geth. then roundchange and start new round. for qman, don't roundchange, it is not necessary.
    77  
    78  			if err := msg.Decode(&rc); err != nil {
    79  			logger.Error("Failed to decode round change", "err", err)
    80  			return errInvalidMessage
    81  	}
    82  
    83  		cv := c.currentView()
    84  		//log.Info("I'm  not the Qmanager(handleRoundChange) ")
    85  
    86  		// We never accept round change message with different sequence number
    87  		if rc.Sequence.Cmp(cv.Sequence) != 0 {
    88  			logger.Warn("Inconsistent sequence number(handleRoundChange)", "expected", cv.Sequence, "got", rc.Sequence)
    89              // sequence no가 틀리면, 블럭 싱크 다시 맞춰주기 위해서, 싱크로나이즈 동작 수행 해주면 됨. 여기서,
    90              // 싱크로나이즈를 수행하기 위해서 여기서 싱크코드 넣고, 시퀀스 맞춰지면,, 다시 startNewRound. 수행
    91              // 메시지 fail 나는 경우, remove peer를 하기 때문에 쓸모없는 peer로,, 에러메시지 나오고, EOF,, 등등.
    92              // 싱크 에러와, fetcher를,, 여기서 채널로,, fetcher or sync hanlder로,, 채널을 통해서 메시지르 보내면,
    93              // eth/handler.go 의 synloop()에서,, 처리되게할 것.
    94  
    95  			//c.startNewRound(&podc.View{
    96  			//	Round:    new(big.Int).Set(rc.Round),
    97  			//	Sequence: new(big.Int).Set(rc.Sequence),
    98  			//}, true)
    99           //   startsync <- 1
   100  
   101  			return errInvalidMessage
   102  		}
   103  
   104  		// We never accept round change message with smaller round number
   105  		if rc.Round.Cmp(cv.Round) < 0 {
   106  			logger.Warn("Old round change", "from", src, "expected", cv.Round, "got", rc.Round)
   107  			return errOldMessage
   108  		}
   109  
   110  		num, err := c.roundChangeSet.Add(rc.Round, msg)
   111  
   112  		if err != nil {
   113  			logger.Warn("Failed to add round change message", "from", src, "msg", msg, "err", err)
   114  			return err
   115  		}
   116  
   117  		// Once we received f+1 round change messages, those messages form a weak certificate.
   118  		// If our round number is smaller than the certificate's round number, we would
   119  		// try to catch up the round number.
   120  		if c.waitingForRoundChange && num == int(c.valSet.F()+1) {
   121  			if cv.Round.Cmp(rc.Round) < 0 {
   122  				c.sendRoundChange(rc.Round)
   123  			}
   124  		}
   125  
   126  		// We've received 2f+1 round change messages, start a new round immediately.
   127  		if num == int(2*c.valSet.F()+1) {
   128  			c.startNewRound(&podc.View{
   129  				Round:    new(big.Int).Set(rc.Round),
   130  				Sequence: new(big.Int).Set(rc.Sequence),
   131  			}, true)
   132  		}
   133  
   134  		//}
   135  	//}
   136  
   137  	return nil
   138  }
   139  
   140  // ----------------------------------------------------------------------------
   141  
   142  func newRoundChangeSet(valSet podc.ValidatorSet) *roundChangeSet {
   143  	return &roundChangeSet{
   144  		validatorSet: valSet,
   145  		roundChanges: make(map[uint64]*messageSet),
   146  		mu:           new(sync.Mutex),
   147  	}
   148  }
   149  
   150  type roundChangeSet struct {
   151  	validatorSet podc.ValidatorSet
   152  	roundChanges map[uint64]*messageSet
   153  	mu           *sync.Mutex
   154  }
   155  
   156  // Add adds the round and message into round change set
   157  func (rcs *roundChangeSet) Add(r *big.Int, msg *message) (int, error) {
   158  	rcs.mu.Lock()
   159  	defer rcs.mu.Unlock()
   160  
   161  	round := r.Uint64()
   162  	if rcs.roundChanges[round] == nil {
   163  		rcs.roundChanges[round] = newMessageSet(rcs.validatorSet)
   164  	}
   165  	err := rcs.roundChanges[round].Add(msg)  //?
   166  	if err != nil {
   167  		return 0, err
   168  	}
   169  	return rcs.roundChanges[round].Size(), nil
   170  }
   171  // Add adds the round and message into round change set
   172  func (rcs *roundChangeSet) Set(r *big.Int, msg *message) (int, error) {
   173  	rcs.mu.Lock()
   174  	defer rcs.mu.Unlock()
   175  
   176  	round := r.Uint64()
   177  	//log.Info("round in Set =", "round", round ) //added by yichoi
   178  	if rcs.roundChanges[round] == nil {
   179  		rcs.roundChanges[round] = newMessageSet(rcs.validatorSet)
   180  	}
   181  	//err := rcs.roundChanges[round].Add(msg)
   182  	//if err != nil {
   183  	//	return 0, err
   184  	//}
   185  	return rcs.roundChanges[round].Size(), nil
   186  }
   187  
   188  // Clear deletes the messages with smaller round
   189  func (rcs *roundChangeSet) Clear(round *big.Int) {
   190  	rcs.mu.Lock()
   191  	defer rcs.mu.Unlock()
   192  
   193  	for k, rms := range rcs.roundChanges {
   194  		if len(rms.Values()) == 0 || k < round.Uint64() {
   195  			delete(rcs.roundChanges, k)
   196  		}
   197  	}
   198  }
   199  
   200  // MaxRound returns the max round which the number of messages is equal or larger than num
   201  func (rcs *roundChangeSet) MaxRound(num int) *big.Int {
   202  	rcs.mu.Lock()
   203  	defer rcs.mu.Unlock()
   204  
   205  	var maxRound *big.Int
   206  	for k, rms := range rcs.roundChanges {
   207  		if rms.Size() < num {
   208  			continue
   209  		}
   210  		r := big.NewInt(int64(k))
   211  		if maxRound == nil || maxRound.Cmp(r) < 0 {
   212  			maxRound = r
   213  		}
   214  	}
   215  	return maxRound
   216  }