Repository navigation
fix(net): gate peer traffic on hello validation and enforce timeout #6993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
317787106
wants to merge
10
commits into
tronprotocol:release_v4.8.3
Choose a base branch
from
317787106:fix/hello_check
base: release_v4.8.3
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,057
−31
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
39b143f
fix the bug of check of hellomessage
317787106 8aef230
Merge branch 'release_v4.8.3' into fix/hello_check
317787106 196a65c
Merge branch 'release_v4.8.3' into fix/hello_check
317787106 183216c
valid HelloMessage before toString
317787106 31861e5
add validEndPoint for HelloMessage
317787106 efcb9b3
remove fork detect
317787106 639130f
don't print hash of hellomessage
317787106 0f7ccda
remove PeerHelloTimeoutTest
317787106 f8e310d
add validation of node id's length; move HandshakeService's valid bef…
317787106 e1cdeff
chore: merge release_v4.8.3 into fix/hello_check
317787106 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
202 changes: 202 additions & 0 deletions
202
framework/src/test/java/org/tron/core/net/P2pHelloGateTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| package org.tron.core.net; | ||
|
|
||
| import static org.mockito.ArgumentMatchers.any; | ||
| import static org.mockito.ArgumentMatchers.eq; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.never; | ||
| import static org.mockito.Mockito.times; | ||
| import static org.mockito.Mockito.verify; | ||
| import static org.mockito.Mockito.verifyNoInteractions; | ||
| import static org.mockito.Mockito.when; | ||
|
|
||
| import java.util.Collections; | ||
| import org.junit.After; | ||
| import org.junit.Before; | ||
| import org.junit.Test; | ||
| import org.mockito.InjectMocks; | ||
| import org.mockito.Mock; | ||
| import org.mockito.MockedStatic; | ||
| import org.mockito.Mockito; | ||
| import org.mockito.MockitoAnnotations; | ||
| import org.tron.common.utils.Sha256Hash; | ||
| import org.tron.consensus.pbft.message.PbftMessage; | ||
| import org.tron.core.ChainBaseManager; | ||
| import org.tron.core.ChainBaseManager.NodeType; | ||
| import org.tron.core.capsule.BlockCapsule.BlockId; | ||
| import org.tron.core.net.message.MessageTypes; | ||
| import org.tron.core.net.message.PbftMessageFactory; | ||
| import org.tron.core.net.message.TronMessageFactory; | ||
| import org.tron.core.net.message.adv.InventoryMessage; | ||
| import org.tron.core.net.message.base.DisconnectMessage; | ||
| import org.tron.core.net.message.handshake.HelloMessage; | ||
| import org.tron.core.net.message.keepalive.PingMessage; | ||
| import org.tron.core.net.messagehandler.BlockMsgHandler; | ||
| import org.tron.core.net.messagehandler.ChainInventoryMsgHandler; | ||
| import org.tron.core.net.messagehandler.FetchInvDataMsgHandler; | ||
| import org.tron.core.net.messagehandler.InventoryMsgHandler; | ||
| import org.tron.core.net.messagehandler.PbftDataSyncHandler; | ||
| import org.tron.core.net.messagehandler.PbftMsgHandler; | ||
| import org.tron.core.net.messagehandler.SyncBlockChainMsgHandler; | ||
| import org.tron.core.net.messagehandler.TransactionsMsgHandler; | ||
| import org.tron.core.net.peer.PeerConnection; | ||
| import org.tron.core.net.peer.PeerManager; | ||
| import org.tron.core.net.service.handshake.HandshakeService; | ||
| import org.tron.core.net.service.keepalive.KeepAliveService; | ||
| import org.tron.core.net.service.statistics.NodeStatistics; | ||
| import org.tron.core.net.service.statistics.PeerStatistics; | ||
| import org.tron.p2p.connection.Channel; | ||
| import org.tron.p2p.discover.Node; | ||
| import org.tron.protos.Protocol.Inventory.InventoryType; | ||
| import org.tron.protos.Protocol.ReasonCode; | ||
|
|
||
| public class P2pHelloGateTest { | ||
|
|
||
| @InjectMocks | ||
| private P2pEventHandlerImpl handler; | ||
| @Mock | ||
| private HandshakeService handshakeService; | ||
| @Mock | ||
| private KeepAliveService keepAliveService; | ||
| @Mock | ||
| private SyncBlockChainMsgHandler syncBlockChainMsgHandler; | ||
| @Mock | ||
| private ChainInventoryMsgHandler chainInventoryMsgHandler; | ||
| @Mock | ||
| private InventoryMsgHandler inventoryMsgHandler; | ||
| @Mock | ||
| private FetchInvDataMsgHandler fetchInvDataMsgHandler; | ||
| @Mock | ||
| private BlockMsgHandler blockMsgHandler; | ||
| @Mock | ||
| private TransactionsMsgHandler transactionsMsgHandler; | ||
| @Mock | ||
| private PbftDataSyncHandler pbftDataSyncHandler; | ||
| @Mock | ||
| private PbftMsgHandler pbftMsgHandler; | ||
| @Mock | ||
| private PeerConnection peer; | ||
| @Mock | ||
| private Channel channel; | ||
|
|
||
| private AutoCloseable mocks; | ||
| private MockedStatic<PeerManager> peerManager; | ||
|
|
||
| @Before | ||
| public void setUp() { | ||
| mocks = MockitoAnnotations.openMocks(this); | ||
| peerManager = Mockito.mockStatic(PeerManager.class); | ||
| peerManager.when(() -> PeerManager.getPeerConnection(channel)).thenReturn(peer); | ||
| } | ||
|
|
||
| @After | ||
| public void tearDown() throws Exception { | ||
| peerManager.close(); | ||
| mocks.close(); | ||
| } | ||
|
|
||
| @Test | ||
| public void testRejectAllOtherMessageTypesBeforeParsing() { | ||
| try (MockedStatic<TronMessageFactory> tronFactory = | ||
| Mockito.mockStatic(TronMessageFactory.class); | ||
| MockedStatic<PbftMessageFactory> pbftFactory = | ||
| Mockito.mockStatic(PbftMessageFactory.class)) { | ||
| int rejected = 0; | ||
| for (MessageTypes type : MessageTypes.values()) { | ||
| if (type != MessageTypes.P2P_HELLO && type != MessageTypes.P2P_DISCONNECT) { | ||
| handler.onMessage(channel, new byte[] {type.asByte()}); | ||
| rejected++; | ||
| } | ||
| } | ||
| verify(peer, times(rejected)).disconnect(ReasonCode.BAD_PROTOCOL); | ||
| tronFactory.verifyNoInteractions(); | ||
| pbftFactory.verifyNoInteractions(); | ||
| } | ||
| verify(peer, never()).getPeerStatistics(); | ||
| verifyNoInteractions(handshakeService, keepAliveService, syncBlockChainMsgHandler, | ||
| chainInventoryMsgHandler, inventoryMsgHandler, fetchInvDataMsgHandler, blockMsgHandler, | ||
| transactionsMsgHandler, pbftDataSyncHandler, pbftMsgHandler); | ||
| } | ||
|
|
||
| @Test | ||
| public void testEmptyFramesAreRejected() { | ||
| handler.onMessage(channel, new byte[0]); | ||
| handler.onMessage(channel, null); | ||
| verify(peer, times(2)).disconnect(ReasonCode.BAD_PROTOCOL); | ||
| } | ||
|
|
||
| @Test | ||
| public void testUnknownPeerIsIgnored() { | ||
| peerManager.when(() -> PeerManager.getPeerConnection(channel)).thenReturn(null); | ||
| handler.onMessage(channel, new PingMessage().getSendBytes()); | ||
| verifyNoInteractions(peer, keepAliveService); | ||
| } | ||
|
|
||
| @Test | ||
| public void testHelloIsDispatchedBeforeHandshake() throws Exception { | ||
| ChainBaseManager chain = mock(ChainBaseManager.class); | ||
| when(chain.getGenesisBlockId()).thenReturn(new BlockId()); | ||
| when(chain.getSolidBlockId()).thenReturn(new BlockId()); | ||
| when(chain.getHeadBlockId()).thenReturn(new BlockId()); | ||
| when(chain.getNodeType()).thenReturn(NodeType.FULL); | ||
| HelloMessage hello = new HelloMessage( | ||
| new Node(new byte[64], "127.0.0.1", null, 18888), 0, chain); | ||
| when(peer.getPeerStatistics()).thenReturn(new PeerStatistics()); | ||
|
|
||
| handler.onMessage(channel, hello.getSendBytes()); | ||
|
|
||
| verify(handshakeService).processHelloMessage(eq(peer), any(HelloMessage.class)); | ||
| verify(peer, never()).disconnect(any()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testDisconnectIsDispatchedBeforeHandshake() { | ||
| NodeStatistics stats = mock(NodeStatistics.class); | ||
| when(peer.getPeerStatistics()).thenReturn(new PeerStatistics()); | ||
| when(peer.getP2pRateLimiter()).thenReturn(new P2pRateLimiter()); | ||
| when(peer.getChannel()).thenReturn(channel); | ||
| when(peer.getNodeStatistics()).thenReturn(stats); | ||
|
|
||
| handler.onMessage(channel, new DisconnectMessage(ReasonCode.PEER_QUITING).getSendBytes()); | ||
|
|
||
| verify(channel).close(); | ||
| verify(stats).nodeDisconnectedRemote(ReasonCode.PEER_QUITING); | ||
| verify(peer, never()).disconnect(any()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testKeepAliveIsDispatchedAfterHello() throws Exception { | ||
| when(peer.getHelloMessageReceive()).thenReturn(mock(HelloMessage.class)); | ||
| when(peer.getPeerStatistics()).thenReturn(new PeerStatistics()); | ||
|
|
||
| handler.onMessage(channel, new PingMessage().getSendBytes()); | ||
|
|
||
| verify(keepAliveService).processMessage(eq(peer), any(PingMessage.class)); | ||
| verify(peer, never()).disconnect(any()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testInventoryIsDispatchedAfterHello() throws Exception { | ||
| when(peer.getHelloMessageReceive()).thenReturn(mock(HelloMessage.class)); | ||
| when(peer.getPeerStatistics()).thenReturn(new PeerStatistics()); | ||
| InventoryMessage inventory = new InventoryMessage( | ||
| Collections.singletonList(Sha256Hash.ZERO_HASH), InventoryType.BLOCK); | ||
|
|
||
| handler.onMessage(channel, inventory.getSendBytes()); | ||
|
|
||
| verify(inventoryMsgHandler).processMessage(eq(peer), any(InventoryMessage.class)); | ||
| verify(peer, never()).disconnect(any()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testPbftIsDispatchedAfterHello() throws Exception { | ||
| when(peer.getHelloMessageReceive()).thenReturn(mock(HelloMessage.class)); | ||
| byte[] data = new byte[] {MessageTypes.PBFT_MSG.asByte()}; | ||
| PbftMessage message = mock(PbftMessage.class); | ||
| try (MockedStatic<PbftMessageFactory> factory = Mockito.mockStatic(PbftMessageFactory.class)) { | ||
| factory.when(() -> PbftMessageFactory.create(data)).thenReturn(message); | ||
| handler.onMessage(channel, data); | ||
| verify(pbftMsgHandler).processMessage(peer, message); | ||
| verify(peer, never()).disconnect(any()); | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.