github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/backend/handler.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 backend
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"io/ioutil"
    23  	"math/big"
    24  	"reflect"
    25  
    26  	"github.com/bigzoro/my_simplechain/common"
    27  	"github.com/bigzoro/my_simplechain/consensus"
    28  	"github.com/bigzoro/my_simplechain/consensus/pbft"
    29  	"github.com/bigzoro/my_simplechain/consensus/pbft/validator"
    30  	"github.com/bigzoro/my_simplechain/core/types"
    31  	"github.com/bigzoro/my_simplechain/log"
    32  	"github.com/bigzoro/my_simplechain/p2p"
    33  	lru "github.com/hashicorp/golang-lru"
    34  )
    35  
    36  const (
    37  	PbftMsg     = 0x11
    38  	NewBlockMsg = 0x07
    39  )
    40  
    41  var (
    42  	// errDecodeFailed is returned when decode message fails
    43  	errDecodeFailed = errors.New("fail to decode istanbul message")
    44  )
    45  
    46  func (sb *backend) decode(msg p2p.Msg) ([]byte, common.Hash, error) {
    47  	var data []byte
    48  	if err := msg.Decode(&data); err != nil {
    49  		return nil, common.Hash{}, errDecodeFailed
    50  	}
    51  
    52  	return data, pbft.RLPHash(data), nil
    53  }
    54  
    55  // HandleMsg implements consensus.Handler.HandleMsg
    56  func (sb *backend) HandleMsg(addr common.Address, msg p2p.Msg) (bool, error) {
    57  	sb.coreMu.Lock()
    58  	defer sb.coreMu.Unlock()
    59  
    60  	if msg.Code == PbftMsg {
    61  		if !sb.coreStarted {
    62  			return true, pbft.ErrStoppedEngine
    63  		}
    64  
    65  		data, hash, err := sb.decode(msg)
    66  		if err != nil {
    67  			return true, errDecodeFailed
    68  		}
    69  
    70  		// Mark peer's message
    71  		ms, ok := sb.recentMessages.Get(addr)
    72  		var m *lru.ARCCache
    73  		if ok {
    74  			m, _ = ms.(*lru.ARCCache)
    75  		} else {
    76  			m, _ = lru.NewARC(inmemoryMessages)
    77  			sb.recentMessages.Add(addr, m)
    78  		}
    79  		m.Add(hash, true)
    80  
    81  		// Mark self known message
    82  		if _, ok := sb.knownMessages.Get(hash); ok {
    83  			return true, nil
    84  		}
    85  		sb.knownMessages.Add(hash, true)
    86  
    87  		go sb.pbftEventMux.Post(pbft.MessageEvent{
    88  			Payload: data,
    89  		})
    90  
    91  		return true, nil
    92  	}
    93  	if msg.Code == NewBlockMsg && sb.core.IsProposer() { // eth.NewBlockMsg: import cycle
    94  		// this case is to safeguard the race of similar block which gets propagated from other node while this node is proposing
    95  		// as p2p.Msg can only be decoded once (get EOF for any subsequence read), we need to make sure the payload is restored after we decode it
    96  		log.Debug("Proposer received NewBlockMsg", "size", msg.Size, "payload.type", reflect.TypeOf(msg.Payload), "sender", addr)
    97  		if reader, ok := msg.Payload.(*bytes.Reader); ok {
    98  			payload, err := ioutil.ReadAll(reader)
    99  			if err != nil {
   100  				return true, err
   101  			}
   102  			reader.Reset(payload)       // ready to be decoded
   103  			defer reader.Reset(payload) // restore so main eth/handler can decode
   104  			var request struct {        // this has to be same as eth/protocol.go#newBlockData as we are reading NewBlockMsg
   105  				Block *types.Block
   106  				TD    *big.Int
   107  			}
   108  			if err := msg.Decode(&request); err != nil {
   109  				log.Debug("Proposer was unable to decode the NewBlockMsg", "error", err)
   110  				return false, nil
   111  			}
   112  			newRequestedBlock := request.Block
   113  			if newRequestedBlock.Header().MixDigest == types.PbftDigest && sb.core.IsCurrentProposal(newRequestedBlock.PendingHash()) {
   114  				log.Debug("Proposer already proposed this block", "hash", newRequestedBlock.Hash(), "proposalHash", newRequestedBlock.PendingHash(), "sender", addr)
   115  				return true, nil
   116  			}
   117  		}
   118  	}
   119  	return false, nil
   120  }
   121  
   122  func (sb *backend) CurrentValidators() ([]common.Address, int) {
   123  	var validators pbft.ValidatorSet
   124  	if sb.currentBlock == nil || sb.currentBlock() == nil {
   125  		validators = validator.NewSet(nil, sb.config.ProposerPolicy)
   126  	} else {
   127  		current := sb.currentBlock()
   128  		validators = sb.getValidators(current.NumberU64(), current.Hash())
   129  	}
   130  	var (
   131  		addresses = make([]common.Address, 0, validators.Size())
   132  		index     = -1
   133  	)
   134  
   135  	for i, v := range validators.List() {
   136  		if sb.address == v.Address() {
   137  			index = i
   138  		}
   139  		addresses = append(addresses, v.Address())
   140  	}
   141  	return addresses, index
   142  }
   143  
   144  // SetBroadcaster implements consensus.Handler.SetBroadcaster
   145  func (sb *backend) SetBroadcaster(broadcaster consensus.Broadcaster) {
   146  	sb.broadcaster = broadcaster
   147  }
   148  
   149  //func (sb *backend) SetSealer(worker consensus.Sealer) {
   150  //	sb.sealer = worker
   151  //}
   152  //
   153  //func (sb *backend) SetTxPool(pool consensus.TxPool) {
   154  //	sb.txPool = pool
   155  //}
   156  //
   157  //func (sb *backend) SetChainWriter(writer consensus.ChainWriter) {
   158  //	sb.chainWriter = writer
   159  //}
   160  
   161  func (sb *backend) NewChainHead(block *types.Block) error {
   162  	sb.coreMu.RLock()
   163  	defer sb.coreMu.RUnlock()
   164  	if !sb.coreStarted {
   165  		return pbft.ErrStoppedEngine
   166  	}
   167  	go sb.pbftEventMux.Post(pbft.FinalCommittedEvent{Committed: block})
   168  	// add proposal2conclusion mapping
   169  	sb.proposal2conclusion.Add(block.PendingHash(), block.Hash())
   170  	// commit chain writer
   171  	sb.chainWriter.CommitBlock(block)
   172  	return nil
   173  }