github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/backend/handler.go (about)

     1  package backend
     2  
     3  import (
     4  	"errors"
     5  
     6  	lru "github.com/hashicorp/golang-lru"
     7  	"github.com/quickchainproject/quickchain/common"
     8  	"github.com/quickchainproject/quickchain/consensus"
     9  	bft "github.com/quickchainproject/quickchain/consensus/dbft"
    10  	"github.com/quickchainproject/quickchain/p2p"
    11  )
    12  
    13  const (
    14  	bftMsg = 0x15
    15  )
    16  
    17  var (
    18  	// errDecodeFailed is returned when decode message fails
    19  	errDecodeFailed = errors.New("fail to decode bft message")
    20  )
    21  
    22  // Protocol implements consensus.Engine.Protocol
    23  func (sb *backend) Protocol() consensus.Protocol {
    24  	return consensus.Protocol{
    25  		Name:     "dbft",
    26  		Versions: []uint{64},
    27  		Lengths:  []uint64{18},
    28  	}
    29  }
    30  
    31  // HandleMsg implements consensus.Handler.HandleMsg
    32  func (sb *backend) HandleMsg(addr common.Address, msg p2p.Msg) (bool, error) {
    33  	sb.coreMu.Lock()
    34  	defer sb.coreMu.Unlock()
    35  
    36  	if msg.Code == bftMsg {
    37  		if !sb.coreStarted {
    38  			return true, bft.ErrStoppedEngine
    39  		}
    40  
    41  		var data []byte
    42  		if err := msg.Decode(&data); err != nil {
    43  			return true, errDecodeFailed
    44  		}
    45  
    46  		hash := bft.RLPHash(data)
    47  
    48  		// Mark peer's message
    49  		ms, ok := sb.recentMessages.Get(addr)
    50  		var m *lru.ARCCache
    51  		if ok {
    52  			m, _ = ms.(*lru.ARCCache)
    53  		} else {
    54  			m, _ = lru.NewARC(inmemoryMessages)
    55  			sb.recentMessages.Add(addr, m)
    56  		}
    57  		m.Add(hash, true)
    58  
    59  		// Mark self known message
    60  		if _, ok := sb.knownMessages.Get(hash); ok {
    61  			return true, nil
    62  		}
    63  		sb.knownMessages.Add(hash, true)
    64  
    65  		go sb.bftEventMux.Post(bft.MessageEvent{
    66  			Payload: data,
    67  		})
    68  
    69  		return true, nil
    70  	}
    71  	return false, nil
    72  }
    73  
    74  // SetBroadcaster implements consensus.Handler.SetBroadcaster
    75  func (sb *backend) SetBroadcaster(broadcaster consensus.Broadcaster) {
    76  	sb.broadcaster = broadcaster
    77  }
    78  
    79  func (sb *backend) NewChainHead() error {
    80  	sb.coreMu.RLock()
    81  	defer sb.coreMu.RUnlock()
    82  	if !sb.coreStarted {
    83  		return bft.ErrStoppedEngine
    84  	}
    85  	go sb.bftEventMux.Post(bft.FinalCommittedEvent{})
    86  	return nil
    87  }