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 }