2023-04-10 18:36:45 +08:00
|
|
|
package eth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/core"
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/ethereum/go-ethereum/eth/protocols/bsc"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
|
|
)
|
|
|
|
|
|
|
|
// bscHandler implements the bsc.Backend interface to handle the various network
|
|
|
|
// packets that are sent as broadcasts.
|
|
|
|
type bscHandler handler
|
|
|
|
|
|
|
|
func (h *bscHandler) Chain() *core.BlockChain { return h.chain }
|
|
|
|
|
|
|
|
// RunPeer is invoked when a peer joins on the `bsc` protocol.
|
|
|
|
func (h *bscHandler) RunPeer(peer *bsc.Peer, hand bsc.Handler) error {
|
|
|
|
if err := peer.Handshake(); err != nil {
|
|
|
|
// ensure that waitBscExtension receives the exit signal normally
|
|
|
|
// otherwise, can't graceful shutdown
|
|
|
|
ps := h.peers
|
|
|
|
id := peer.ID()
|
|
|
|
|
|
|
|
// Ensure nobody can double connect
|
|
|
|
ps.lock.Lock()
|
|
|
|
if wait, ok := ps.bscWait[id]; ok {
|
|
|
|
delete(ps.bscWait, id)
|
2023-05-06 09:48:54 +08:00
|
|
|
peer.Log().Error("Bsc extension Handshake failed", "err", err)
|
2023-04-19 16:19:14 +08:00
|
|
|
wait <- nil
|
2023-04-10 18:36:45 +08:00
|
|
|
}
|
|
|
|
ps.lock.Unlock()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return (*handler)(h).runBscExtension(peer, hand)
|
|
|
|
}
|
|
|
|
|
|
|
|
// PeerInfo retrieves all known `bsc` information about a peer.
|
|
|
|
func (h *bscHandler) PeerInfo(id enode.ID) interface{} {
|
|
|
|
if p := h.peers.peer(id.String()); p != nil && p.bscExt != nil {
|
|
|
|
return p.bscExt.info()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle is invoked from a peer's message handler when it receives a new remote
|
|
|
|
// message that the handler couldn't consume and serve itself.
|
|
|
|
func (h *bscHandler) Handle(peer *bsc.Peer, packet bsc.Packet) error {
|
|
|
|
// DeliverSnapPacket is invoked from a peer's message handler when it transmits a
|
|
|
|
// data packet for the local node to consume.
|
|
|
|
switch packet := packet.(type) {
|
|
|
|
case *bsc.VotesPacket:
|
|
|
|
return h.handleVotesBroadcast(peer, packet.Votes)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unexpected bsc packet type: %T", packet)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleVotesBroadcast is invoked from a peer's message handler when it transmits a
|
|
|
|
// votes broadcast for the local node to process.
|
|
|
|
func (h *bscHandler) handleVotesBroadcast(peer *bsc.Peer, votes []*types.VoteEnvelope) error {
|
2023-07-11 10:13:08 +08:00
|
|
|
if peer.IsOverLimitAfterReceiving() {
|
|
|
|
return nil
|
2023-04-10 18:36:45 +08:00
|
|
|
}
|
2023-07-11 10:13:08 +08:00
|
|
|
// Here we only put the first vote, to avoid ddos attack by sending a large batch of votes.
|
|
|
|
// This won't abandon any valid vote, because one vote is sent every time referring to func voteBroadcastLoop
|
|
|
|
if len(votes) > 0 {
|
|
|
|
h.votepool.PutVote(votes[0])
|
|
|
|
}
|
|
|
|
|
2023-04-10 18:36:45 +08:00
|
|
|
return nil
|
|
|
|
}
|