github.com/klaytn/klaytn@v1.10.2/consensus/istanbul/backend/handler.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2017 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from quorum/consensus/istanbul/backend/handler.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package backend 22 23 import ( 24 "errors" 25 26 lru "github.com/hashicorp/golang-lru" 27 "github.com/klaytn/klaytn/common" 28 "github.com/klaytn/klaytn/consensus" 29 "github.com/klaytn/klaytn/consensus/istanbul" 30 "github.com/klaytn/klaytn/networks/p2p" 31 ) 32 33 const ( 34 IstanbulMsg = 0x11 35 ) 36 37 var ( 38 // errDecodeFailed is returned when decode message fails 39 errDecodeFailed = errors.New("fail to decode istanbul message") 40 errNoChainReader = errors.New("sb.chain is nil! --mine option might be missing") 41 errInvalidPeerAddress = errors.New("invalid address") 42 43 // TODO-Klaytn-Istanbul: define Versions and Lengths with correct values. 44 IstanbulProtocol = consensus.Protocol{ 45 Name: "istanbul", 46 Versions: []uint{65, 64}, 47 Lengths: []uint64{23, 21}, 48 } 49 ) 50 51 // Protocol implements consensus.Engine.Protocol 52 func (sb *backend) Protocol() consensus.Protocol { 53 return IstanbulProtocol 54 } 55 56 // HandleMsg implements consensus.Handler.HandleMsg 57 func (sb *backend) HandleMsg(addr common.Address, msg p2p.Msg) (bool, error) { 58 sb.coreMu.Lock() 59 defer sb.coreMu.Unlock() 60 61 if msg.Code == IstanbulMsg { 62 if !sb.coreStarted { 63 return true, istanbul.ErrStoppedEngine 64 } 65 66 var cmsg istanbul.ConsensusMsg 67 68 // var data []byte 69 if err := msg.Decode(&cmsg); err != nil { 70 return true, errDecodeFailed 71 } 72 data := cmsg.Payload 73 hash := istanbul.RLPHash(data) 74 75 // Mark peer's message 76 var m *lru.ARCCache 77 ms, ok := sb.recentMessages.Get(addr) 78 if ok { 79 m, _ = ms.(*lru.ARCCache) 80 } else { 81 m, _ = lru.NewARC(inmemoryMessages) 82 sb.recentMessages.Add(addr, m) 83 } 84 m.Add(hash, true) 85 86 // Mark self known message 87 if _, ok := sb.knownMessages.Get(hash); ok { 88 return true, nil 89 } 90 sb.knownMessages.Add(hash, true) 91 92 go sb.istanbulEventMux.Post(istanbul.MessageEvent{ 93 Payload: data, 94 Hash: cmsg.PrevHash, 95 }) 96 97 return true, nil 98 } 99 return false, nil 100 } 101 102 func (sb *backend) ValidatePeerType(addr common.Address) error { 103 // istanbul.Start vs try to connect by peer 104 for sb.chain == nil { 105 return errNoChainReader 106 } 107 validators := sb.getValidators(sb.chain.CurrentHeader().Number.Uint64(), sb.chain.CurrentHeader().Hash()) 108 for _, val := range validators.List() { 109 if addr == val.Address() { 110 return nil 111 } 112 } 113 for _, val := range validators.DemotedList() { 114 if addr == val.Address() { 115 return nil 116 } 117 } 118 return errInvalidPeerAddress 119 } 120 121 // SetBroadcaster implements consensus.Handler.SetBroadcaster 122 func (sb *backend) SetBroadcaster(broadcaster consensus.Broadcaster, nodetype common.ConnType) { 123 sb.broadcaster = broadcaster 124 if nodetype == common.CONSENSUSNODE { 125 sb.broadcaster.RegisterValidator(common.CONSENSUSNODE, sb) 126 } 127 } 128 129 // RegisterConsensusMsgCode registers the channel of consensus msg. 130 func (sb *backend) RegisterConsensusMsgCode(peer consensus.Peer) { 131 if err := peer.RegisterConsensusMsgCode(IstanbulMsg); err != nil { 132 logger.Error("RegisterConsensusMsgCode failed", "err", err) 133 } 134 } 135 136 func (sb *backend) NewChainHead() error { 137 sb.coreMu.RLock() 138 defer sb.coreMu.RUnlock() 139 if !sb.coreStarted { 140 return istanbul.ErrStoppedEngine 141 } 142 143 go sb.istanbulEventMux.Post(istanbul.FinalCommittedEvent{}) 144 return nil 145 }