Skip to content

Commit 805f5b5

Browse files
wbwb
authored andcommitted
feat(net): add P2P message deduplication and length validation
- FetchInvDataMsgHandler: reject messages with duplicate hashes - TransactionsMsgHandler: reject messages with duplicate transactions - SyncBlockChainMsgHandler: reject blockIds list exceeding 30 entries - Add MAX_SYNC_CHAIN_IDS = 30 constant to NetConstants - Add unit tests covering duplicate rejection and boundary values All violations throw P2pException(BAD_MESSAGE), triggering peer disconnect via existing P2pEventHandlerImpl error path.
1 parent 9529fb8 commit 805f5b5

17 files changed

Lines changed: 302 additions & 16 deletions

File tree

common/src/main/java/org/tron/common/parameter/CommonParameter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@ public class CommonParameter {
492492
public long pendingTransactionTimeout;
493493
@Getter
494494
@Setter
495+
public int maxTrxCacheSize;
496+
@Getter
497+
@Setter
495498
public boolean nodeMetricsEnable = false;
496499
@Getter
497500
@Setter

common/src/main/java/org/tron/core/config/Parameter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ public class NetConstants {
102102
public static final int MSG_CACHE_DURATION_IN_BLOCKS = 5;
103103
public static final int MAX_BLOCK_FETCH_PER_PEER = 100;
104104
public static final int MAX_TRX_FETCH_PER_PEER = 1000;
105+
public static final int MAX_SYNC_CHAIN_IDS = 30;
105106
}
106107

107108
public class DatabaseConstants {

common/src/main/java/org/tron/core/config/args/NodeConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public class NodeConfig {
8585
private ChannelConfig channel = new ChannelConfig();
8686
private int maxTransactionPendingSize = 2000;
8787
private long pendingTransactionTimeout = 60000;
88+
private int maxTrxCacheSize = 50_000;
8889
private int agreeNodeCount = 0;
8990
private boolean openHistoryQueryWhenLiteFN = false;
9091
private boolean unsolidifiedBlockCheck = false;
@@ -498,6 +499,11 @@ private void postProcess() {
498499
if (dynamicConfig.checkInterval <= 0) {
499500
dynamicConfig.checkInterval = 600;
500501
}
502+
503+
// maxTrxCacheSize: minimum 2000
504+
if (maxTrxCacheSize < 2000) {
505+
maxTrxCacheSize = 2000;
506+
}
501507
}
502508

503509
// ===========================================================================

common/src/main/resources/reference.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ node {
346346
receiveTcpMinDataLength = 2048
347347
maxTransactionPendingSize = 2000
348348
pendingTransactionTimeout = 60000
349+
# total cached trx across handler queues + pending + rePush
350+
maxTrxCacheSize = 50000
349351

350352
# Consensus agreement
351353
agreeNodeCount = 0

framework/src/main/java/org/tron/core/config/args/Args.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ private static void applyNodeConfig(NodeConfig nc) {
625625

626626
PARAMETER.maxTransactionPendingSize = nc.getMaxTransactionPendingSize();
627627
PARAMETER.pendingTransactionTimeout = nc.getPendingTransactionTimeout();
628+
PARAMETER.maxTrxCacheSize = nc.getMaxTrxCacheSize();
628629

629630
PARAMETER.validContractProtoThreadNum = nc.getValidContractProtoThreads();
630631

framework/src/main/java/org/tron/core/db/Manager.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,9 +2085,13 @@ public NullifierStore getNullifierStore() {
20852085
return chainBaseManager.getNullifierStore();
20862086
}
20872087

2088+
public int getCachedTransactionSize() {
2089+
return pushTransactionQueue.size() + getPendingTransactions().size()
2090+
+ getRePushTransactions().size();
2091+
}
2092+
20882093
public boolean isTooManyPending() {
2089-
return getPendingTransactions().size() + getRePushTransactions().size()
2090-
> maxTransactionPendingSize;
2094+
return getCachedTransactionSize() > maxTransactionPendingSize;
20912095
}
20922096

20932097
private void preValidateTransactionSign(List<TransactionCapsule> txs)

framework/src/main/java/org/tron/core/net/TronNetDelegate.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,4 +384,8 @@ public boolean isBlockUnsolidified() {
384384
return headNum - solidNum >= maxUnsolidifiedBlocks;
385385
}
386386

387+
public int getCachedTransactionSize() {
388+
return dbManager.getCachedTransactionSize();
389+
}
390+
387391
}

framework/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.common.cache.Cache;
44
import com.google.common.cache.CacheBuilder;
55
import com.google.common.collect.Lists;
6+
import java.util.HashSet;
67
import java.util.List;
78
import java.util.concurrent.TimeUnit;
89
import lombok.extern.slf4j.Slf4j;
@@ -153,6 +154,12 @@ public boolean isAdvInv(PeerConnection peer, FetchInvDataMessage msg) {
153154

154155
private void check(PeerConnection peer, FetchInvDataMessage fetchInvDataMsg,
155156
boolean isAdv) throws P2pException {
157+
List<Sha256Hash> hashList = fetchInvDataMsg.getHashList();
158+
if (hashList.size() != new HashSet<>(hashList).size()) {
159+
throw new P2pException(TypeEnum.BAD_MESSAGE,
160+
"FetchInvData contains duplicate hashes, size: " + hashList.size());
161+
}
162+
156163
MessageTypes type = fetchInvDataMsg.getInvMessageType();
157164

158165
if (type == MessageTypes.TRX) {

framework/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package org.tron.core.net.messagehandler;
22

3+
import java.util.HashSet;
4+
import java.util.List;
35
import lombok.extern.slf4j.Slf4j;
46
import org.springframework.beans.factory.annotation.Autowired;
57
import org.springframework.stereotype.Component;
68
import org.tron.common.utils.Sha256Hash;
79
import org.tron.core.config.args.Args;
10+
import org.tron.core.exception.P2pException;
11+
import org.tron.core.exception.P2pException.TypeEnum;
812
import org.tron.core.net.TronNetDelegate;
913
import org.tron.core.net.message.TronMessage;
1014
import org.tron.core.net.message.adv.InventoryMessage;
@@ -27,7 +31,7 @@ public class InventoryMsgHandler implements TronMsgHandler {
2731
private TransactionsMsgHandler transactionsMsgHandler;
2832

2933
@Override
30-
public void processMessage(PeerConnection peer, TronMessage msg) {
34+
public void processMessage(PeerConnection peer, TronMessage msg) throws P2pException {
3135
InventoryMessage inventoryMessage = (InventoryMessage) msg;
3236
InventoryType type = inventoryMessage.getInventoryType();
3337

@@ -45,10 +49,17 @@ public void processMessage(PeerConnection peer, TronMessage msg) {
4549
}
4650
}
4751

48-
private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) {
52+
private boolean check(PeerConnection peer, InventoryMessage inventoryMessage)
53+
throws P2pException {
54+
55+
List<Sha256Hash> hashList = inventoryMessage.getHashList();
56+
if (hashList.size() != new HashSet<>(hashList).size()) {
57+
throw new P2pException(TypeEnum.BAD_MESSAGE,
58+
"Inventory contains duplicate hashes, size: " + hashList.size());
59+
}
4960

5061
InventoryType type = inventoryMessage.getInventoryType();
51-
int size = inventoryMessage.getHashList().size();
62+
int size = hashList.size();
5263

5364
if (peer.isNeedSyncFromPeer() || peer.isNeedSyncFromUs()) {
5465
logger.warn("Drop inv: {} size: {} from Peer {}, syncFromUs: {}, syncFromPeer: {}",

framework/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ private boolean check(PeerConnection peer, SyncBlockChainMessage msg) throws P2p
7171
throw new P2pException(TypeEnum.BAD_MESSAGE, "SyncBlockChain blockIds is empty");
7272
}
7373

74+
if (blockIds.size() > NetConstants.MAX_SYNC_CHAIN_IDS) {
75+
throw new P2pException(TypeEnum.BAD_MESSAGE,
76+
"SyncBlockChain blockIds size " + blockIds.size()
77+
+ " exceeds limit " + NetConstants.MAX_SYNC_CHAIN_IDS);
78+
}
79+
7480
BlockId firstId = blockIds.get(0);
7581
if (!tronNetDelegate.containBlockInMainChain(firstId)) {
7682
logger.warn("Sync message from peer {} without the first block: {}",

0 commit comments

Comments
 (0)