github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/consensus/istanbul/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 "errors" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/consensus" 24 "github.com/ethereum/go-ethereum/consensus/istanbul" 25 "github.com/ethereum/go-ethereum/p2p" 26 lru "github.com/hashicorp/golang-lru" 27 ) 28 29 const ( 30 istanbulMsg = 0x11 31 ) 32 33 var ( 34 // errDecodeFailed is returned when decode message fails 35 errDecodeFailed = errors.New("fail to decode istanbul message") 36 ) 37 38 // Protocol implements consensus.Engine.Protocol 39 func (sb *backend) Protocol() consensus.Protocol { 40 return consensus.Protocol{ 41 Name: "istanbul", 42 Versions: []uint{64}, 43 Lengths: []uint64{18}, 44 } 45 } 46 47 // HandleMsg implements consensus.Handler.HandleMsg 48 func (sb *backend) HandleMsg(addr common.Address, msg p2p.Msg) (bool, error) { 49 sb.coreMu.Lock() 50 defer sb.coreMu.Unlock() 51 52 if msg.Code == istanbulMsg { 53 if !sb.coreStarted { 54 return true, istanbul.ErrStoppedEngine 55 } 56 57 var data []byte 58 if err := msg.Decode(&data); err != nil { 59 return true, errDecodeFailed 60 } 61 62 hash := istanbul.RLPHash(data) 63 64 // Mark peer's message 65 ms, ok := sb.recentMessages.Get(addr) 66 var m *lru.ARCCache 67 if ok { 68 m, _ = ms.(*lru.ARCCache) 69 } else { 70 m, _ = lru.NewARC(inmemoryMessages) 71 sb.recentMessages.Add(addr, m) 72 } 73 m.Add(hash, true) 74 75 // Mark self known message 76 if _, ok := sb.knownMessages.Get(hash); ok { 77 return true, nil 78 } 79 sb.knownMessages.Add(hash, true) 80 81 go sb.istanbulEventMux.Post(istanbul.MessageEvent{ 82 Payload: data, 83 }) 84 85 return true, nil 86 } 87 return false, nil 88 } 89 90 // SetBroadcaster implements consensus.Handler.SetBroadcaster 91 func (sb *backend) SetBroadcaster(broadcaster consensus.Broadcaster) { 92 sb.broadcaster = broadcaster 93 } 94 95 func (sb *backend) NewChainHead() error { 96 sb.coreMu.RLock() 97 defer sb.coreMu.RUnlock() 98 if !sb.coreStarted { 99 return istanbul.ErrStoppedEngine 100 } 101 go sb.istanbulEventMux.Post(istanbul.FinalCommittedEvent{}) 102 return nil 103 }