Skip to content

Commit

Permalink
fix: support trust mode
Browse files Browse the repository at this point in the history
  • Loading branch information
brilliant-lx committed May 23, 2023
1 parent b6e7ec1 commit 4cc632f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 20 deletions.
28 changes: 17 additions & 11 deletions eth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,22 +391,23 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
}
}
// Ignore maxPeers if this is a trusted peer
if !peer.Peer.Info().Network.Trusted {
peerInfo := peer.Peer.Info()
if !peerInfo.Network.Trusted {
if reject || h.peers.len() >= h.maxPeers {
return p2p.DiscTooManyPeers
}
}

remoteAddr := peer.Peer.Info().Network.RemoteAddress
remoteAddr := peerInfo.Network.RemoteAddress
indexIp := strings.LastIndex(remoteAddr, ":")
if indexIp == -1 {
// there could be no IP address, such as a pipe
peer.Log().Debug("runEthPeer", "no ip address, remoteAddress", remoteAddr)
} else {
} else if !peerInfo.Network.Trusted {
remoteIp := remoteAddr[:indexIp]
if num, ok := h.peersPerIp[remoteIp]; ok && num >= h.maxPeersPerIp {
peer.Log().Info("The IP has too many peers", "ip", remoteIp, "maxPeersPerIp", h.maxPeersPerIp,
"name", peer.Peer.Info().Name, "Enode", peer.Peer.Info().Enode)
"name", peerInfo.Name, "Enode", peerInfo.Enode)
return p2p.DiscTooManyPeers
}

Expand Down Expand Up @@ -647,17 +648,22 @@ func (h *handler) unregisterPeer(id string) {
logger.Error("Ethereum peer removal failed", "err", err)
}

remoteAddr := peer.Peer.Info().Network.RemoteAddress
peerInfo := peer.Peer.Info()
remoteAddr := peerInfo.Network.RemoteAddress
indexIp := strings.LastIndex(remoteAddr, ":")
if indexIp == -1 {
// there could be no IP address, such as a pipe
peer.Log().Debug("unregisterPeer", "name", peer.Peer.Info().Name, "no ip address, remoteAddress", remoteAddr)
} else {
peer.Log().Debug("unregisterPeer", "name", peerInfo.Name, "no ip address, remoteAddress", remoteAddr)
} else if !peerInfo.Network.Trusted {
remoteIp := remoteAddr[:indexIp]
h.peersPerIp[remoteIp] = h.peersPerIp[remoteIp] - 1
logger.Debug("unregisterPeer", "name", peer.Peer.Info().Name, "connectNum", h.peersPerIp[remoteIp])
if h.peersPerIp[remoteIp] == 0 {
delete(h.peersPerIp, remoteIp)
if h.peersPerIp[remoteIp] <= 0 {
peer.Log().Error("unregisterPeer without record", "name", peerInfo.Name, "remoteAddress", remoteAddr)
} else {
h.peersPerIp[remoteIp] = h.peersPerIp[remoteIp] - 1
logger.Debug("unregisterPeer", "name", peerInfo.Name, "connectNum", h.peersPerIp[remoteIp])
if h.peersPerIp[remoteIp] == 0 {
delete(h.peersPerIp, remoteIp)
}
}
}
}
Expand Down
32 changes: 24 additions & 8 deletions eth/handler_eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ func TestOptionMaxPeersPerIp(t *testing.T) {
uniPort = 1000
)

tryFunc := func(tryNum int, ip1 string, ip2 string, doneCh chan struct{}) {
tryFunc := func(tryNum int, ip1 string, ip2 string, trust bool, doneCh chan struct{}) {
// Create a source peer to send messages through and a sink handler to receive them
p2pSrc, p2pSink := p2p.MsgPipe()
defer p2pSrc.Close()
Expand All @@ -954,6 +954,9 @@ func TestOptionMaxPeersPerIp(t *testing.T) {
peer1.UpdateTestRemoteAddr(ip1 + strconv.Itoa(uniPort))
peer2 := p2p.NewPeerPipe(enode.ID{byte(uniPort)}, "", nil, p2pSink)
peer2.UpdateTestRemoteAddr(ip2 + strconv.Itoa(uniPort))
if trust {
peer2.UpdateTrustFlagTest()
}
uniPort++

src := eth.NewPeer(eth.ETH66, peer1, p2pSrc, handler.txpool)
Expand All @@ -970,17 +973,22 @@ func TestOptionMaxPeersPerIp(t *testing.T) {
})
// err is nil, connection ok and it is closed by the doneCh
if err == nil {
// if num > maxPeersPerIp, then err should be p2p.DiscTooManyPeers
if num > maxPeersPerIp {
t.Errorf("current num is %d, maxPeersPerIp is %d, should failed", num, maxPeersPerIp)
if trust || num <= maxPeersPerIp {
return
}
// if num > maxPeersPerIp and not trust, should report: p2p.DiscTooManyPeers
t.Errorf("current num is %d, maxPeersPerIp is %d, should failed", num, maxPeersPerIp)
return
}
wg.Done()
if trust {
t.Errorf("trust node should not failed, num is %d, maxPeersPerIp is %d, but failed:%s", num, maxPeersPerIp, err)
}
// err should be p2p.DiscTooManyPeers and num > maxPeersPerIp
if err == p2p.DiscTooManyPeers && num > maxPeersPerIp {
return
}

t.Errorf("current num is %d, maxPeersPerIp is %d, but failed:%s", num, maxPeersPerIp, err)
}(tryNum)

Expand All @@ -994,28 +1002,36 @@ func TestOptionMaxPeersPerIp(t *testing.T) {
// case 1: normal case
doneCh1 := make(chan struct{})
for tryNum := 1; tryNum <= 4; tryNum++ {
tryFunc(tryNum, "1.2.3.11:", "1.2.3.22:", doneCh1)
tryFunc(tryNum, "1.2.3.11:", "1.2.3.22:", false, doneCh1)
}
close(doneCh1)

// case 2: once the previous connection was unregisterred, new connections with same IP can be accepted.
doneCh2 := make(chan struct{})
for tryNum := 1; tryNum <= 4; tryNum++ {
tryFunc(tryNum, "1.2.3.11:", "1.2.3.22:", doneCh2)
tryFunc(tryNum, "1.2.3.11:", "1.2.3.22:", false, doneCh2)
}
close(doneCh2)

// case 3: ipv6 address, like: [2001:db8::1]:80
doneCh3 := make(chan struct{})
for tryNum := 1; tryNum <= 4; tryNum++ {
tryFunc(tryNum, "[2001:db8::11]:", "[2001:db8::22]:", doneCh3)
tryFunc(tryNum, "[2001:db8::11]:", "[2001:db8::22]:", false, doneCh3)
}
close(doneCh3)

// case 4: same as case 2, but for ipv6
doneCh4 := make(chan struct{})
for tryNum := 1; tryNum <= 4; tryNum++ {
tryFunc(tryNum, "[2001:db8::11]:", "[2001:db8::22]:", doneCh4)
tryFunc(tryNum, "[2001:db8::11]:", "[2001:db8::22]:", false, doneCh4)
}
close(doneCh4)

// case 5: test trust node
doneCh5 := make(chan struct{})
for tryNum := 1; tryNum <= 4; tryNum++ {
tryFunc(tryNum, "[2001:db8::11]:", "[2001:db8::22]:", true, doneCh5)
}
close(doneCh5)

}
6 changes: 5 additions & 1 deletion p2p/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,14 @@ func (p *Peer) RemoteAddr() net.Addr {
return p.rw.fd.RemoteAddr()
}

func (p *Peer) UpdateTestRemoteAddr(addr string) {
func (p *Peer) UpdateTestRemoteAddr(addr string) { // test purpose only
p.testRemoteAddr = addr
}

func (p *Peer) UpdateTrustFlagTest() { // test purpose only
p.rw.set(trustedConn, true)
}

// LocalAddr returns the local address of the network connection.
func (p *Peer) LocalAddr() net.Addr {
return p.rw.fd.LocalAddr()
Expand Down

0 comments on commit 4cc632f

Please sign in to comment.