diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java index 8256875589..3d318386be 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java @@ -1548,7 +1548,8 @@ public LogFilterElement[] getLogs(FilterRequest fr) throws JsonRpcInvalidParamsE } @Override - public LogFilterElement[] getFilterLogs(String filterId) throws ExecutionException, + public LogFilterElement[] getFilterLogs(String filterId) throws + JsonRpcInvalidParamsException, ExecutionException, InterruptedException, BadItemException, ItemNotFoundException, JsonRpcMethodNotFoundException, JsonRpcTooManyResultException { disableInPBFT("eth_getFilterLogs"); @@ -1568,6 +1569,10 @@ public LogFilterElement[] getFilterLogs(String filterId) throws ExecutionExcepti LogFilterWrapper logFilterWrapper = eventFilter2Result.get(filterId).getLogFilterWrapper(); long currentMaxBlockNum = wallet.getNowBlock().getBlockHeader().getRawData().getNumber(); + // re-check the block range against the current head: the filter was created without the cap + // (eth_newFilter), so enforce it here to prevent an unbounded scan. + logFilterWrapper.validateBlockRange(currentMaxBlockNum); + return getLogsByLogFilterWrapper(logFilterWrapper, currentMaxBlockNum); } diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java index 3f9582d482..0fdf174bb5 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/filters/LogFilterWrapper.java @@ -98,16 +98,23 @@ public LogFilterWrapper(FilterRequest fr, long currentMaxBlockNum, Wallet wallet throw new JsonRpcInvalidParamsException("please verify: fromBlock <= toBlock"); } } - - // till now, it needs to check block range for eth_getLogs - int maxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); - if (checkBlockRange && maxBlockRange > 0 - && min(toBlockSrc, currentMaxBlockNum) - fromBlockSrc > maxBlockRange) { - throw new JsonRpcInvalidParamsException("exceed max block range: " + maxBlockRange); - } } this.fromBlock = fromBlockSrc; this.toBlock = toBlockSrc; + + // eth_getLogs enforces the block range at construction time. eth_newFilter creates the + // wrapper with checkBlockRange=false (no creation-time gate); eth_getFilterLogs re-runs this + // check against the current head before scanning so the cap cannot be bypassed. + if (checkBlockRange) { + validateBlockRange(currentMaxBlockNum); + } + } + + public void validateBlockRange(long currentMaxBlockNum) throws JsonRpcInvalidParamsException { + int maxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); + if (maxBlockRange > 0 && min(toBlock, currentMaxBlockNum) - fromBlock > maxBlockRange) { + throw new JsonRpcInvalidParamsException("exceed max block range: " + maxBlockRange); + } } } diff --git a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java index 870ce31766..55c707c2cd 100644 --- a/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java +++ b/framework/src/test/java/org/tron/core/jsonrpc/JsonrpcServiceTest.java @@ -1328,6 +1328,35 @@ public void testLogFilterTagHandling() { } } + @Test + public void testGetFilterLogsEnforcesBlockRange() throws Exception { + int oldMaxBlockRange = Args.getInstance().getJsonRpcMaxBlockRange(); + Args.getInstance().setJsonRpcMaxBlockRange(5_000); + try { + // toBlock=0xf4240 (1_000_000) is clamped to head (LATEST_BLOCK_NUM = 10_000), so the span + // is min(1_000_000, 10_000) - 0 = 10_000 > 5_000 cap. + String wideFilterId = tronJsonRpc.newFilter( + new FilterRequest("0x0", "0xf4240", null, null, null)); + Assert.assertNotNull(wideFilterId); + + // eth_getFilterLogs must reject it at query time (previously bypassed -> unbounded scan). + JsonRpcInvalidParamsException ex = Assert.assertThrows( + JsonRpcInvalidParamsException.class, + () -> tronJsonRpc.getFilterLogs(wideFilterId)); + Assert.assertEquals("exceed max block range: 5000", ex.getMessage()); + + // A within-cap filter (span 0) is still served normally - no false rejection. + String headHex = ByteArray.toJsonHex(blockCapsule1.getNum()); + int expectedLogs = blockCapsule1.getTransactions().size() * 2; + String okFilterId = tronJsonRpc.newFilter( + new FilterRequest(headHex, headHex, null, null, null)); + LogFilterElement[] okResult = tronJsonRpc.getFilterLogs(okFilterId); + Assert.assertEquals(expectedLogs, okResult.length); + } finally { + Args.getInstance().setJsonRpcMaxBlockRange(oldMaxBlockRange); + } + } + @Test public void testGetBlockReceipts() {