Skip to content

fix(API): divide dynamic 2#14

Closed
Sunny6889 wants to merge 2 commits intodevelopfrom
fix_divide_dynamic_2
Closed

fix(API): divide dynamic 2#14
Sunny6889 wants to merge 2 commits intodevelopfrom
fix_divide_dynamic_2

Conversation

@Sunny6889
Copy link
Copy Markdown
Owner

@Sunny6889 Sunny6889 commented Apr 2, 2026

What does this PR do?

Why are these changes required?

This PR has been tested by:

  • Unit Tests
  • Manual Testing

Follow up

Extra details

Summary by CodeRabbit

  • Bug Fixes

    • Fixed potential division by zero errors in energy window calculations to prevent system errors and improve reliability under edge conditions.
  • Refactor

    • Improved rate limiter adapter mechanism with enhanced validation logic and more robust error handling.
  • Tests

    • Added new comprehensive test suite providing coverage for adapter validation and resource management edge cases.

Squashed commits:
[6bd4faa] fix(API): add whitelist rate limiter adapter
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

Three files were updated to improve robustness and security: resource processor gained a clarifying comment, transaction trace added zero-size guards to prevent division by zero, rate limiter servlet replaced dynamic reflection-based adapter loading with a fixed whitelist map, and a new test suite was added to validate the whitelist logic.

Changes

Cohort / File(s) Summary
Documentation Enhancement
chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java
Added clarifying comment for remainUsage variable in increaseV2 method to document that it represents decayed lastUsage. No logic changes.
Division-by-Zero Guards
chainbase/src/main/java/org/tron/core/db/TransactionTrace.java
Updated resetAccountUsage and resetAccountUsageV2 methods to guard against division by zero by conditionally setting newUsage to 0 when calculated newSize equals 0, replacing previous unconditional division computation.
Security Refactoring
framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java
Replaced dynamic adapter loading via reflection (Class.forName) with fixed whitelist map (ALLOWED_ADAPTERS). Updated adapter resolution to use defaults, simplified error handling, removed ADAPTER_PREFIX constant, and added Map-related imports.
Whitelist Validation Tests
framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java
New test suite verifying adapter whitelist contains exactly four expected entries, rejects invalid class names, enforces immutability via UnsupportedOperationException, and validates structural invariants including non-empty state and IRateLimiter implementation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 bounces excitedly
Comments clarify with care,
Guards prevent division's snare,
Whitelists replace reflection's flair,
Tests ensure security's square—
A safer hop everywhere! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'fix(API): divide dynamic 2' is vague and does not clearly convey the main changes. While it hints at division-related fixes, it does not adequately summarize the core work: divide-by-zero fixes, adapter whitelisting, and security hardening. Revise the title to be more specific about the primary change, such as 'fix(API): prevent divide-by-zero and add rate limiter adapter whitelist' or focus on the most critical fix if prioritizing one aspect.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix_divide_dynamic_2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java (1)

33-87: Please add one behavior-level test around servlet initialization.

This suite only inspects the private map. If RateLimiterServlet.addRateContainer() later bypassed the whitelist, these tests would still stay green. One happy-path init test and one unknown-strategy rejection test would cover the security behavior this PR is actually changing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java`
around lines 33 - 87, Add two integration-style tests that exercise servlet
initialization rather than just the private whitelist map: 1) a happy-path test
that instantiates RateLimiterServlet, calls init(...) (using a Mock/Minimal
ServletConfig/ServletContext) with init-params that reference a known key such
as DEFAULT_BASE_QPS or QPS_RATE_LIMITER and then asserts that addRateContainer()
behavior occurred (e.g., the servlet exposes the configured container or a
non-null internal container/state after init); 2) a negative test that calls
init(...) with an unknown/invalid strategy name and asserts the servlet rejects
it (either by throwing ServletException or by leaving the rate-container
unregistered/null). Target the RateLimiterServlet.init(...) and
RateLimiterServlet.addRateContainer(...) code paths so the tests will fail if
init bypasses the ALLOWED_ADAPTERS whitelist.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@chainbase/src/main/java/org/tron/core/db/TransactionTrace.java`:
- Around line 304-305: Persisted zero window sizes in TransactionTrace lead to
divide-by-zero later in ResourceProcessor.increase() when divideCeil(lastUsage *
precision, oldWindowSize) is called; modify the code that writes window sizes
(the expressions that set newUsage/newSize and newUsage/newSize2 in
TransactionTrace) so that when usage is zero you persist a positive fallback
(e.g., use currentSize > 0 ? currentSize : 1L and currentSize2 > 0 ?
currentSize2 : 1L) instead of 0L, ensuring divideCeil never receives a zero
denominator; update the logic around the newUsage computations to use these
non-zero fallbacks while keeping the existing semantics when usage is non-zero.

In
`@framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java`:
- Around line 43-58: The testWhitelistContents() assertions are too permissive:
replace the isAssignableFrom() checks on
allowedAdapters.get(GLOBAL_PREEMPTIBLE), get(QPS_RATE_LIMITER),
get(IP_QPS_RATE_LIMITER), and get(DEFAULT_BASE_QPS) with assertSame(...) against
the exact classes GlobalPreemptibleAdapter.class, QpsRateLimiterAdapter.class,
IPQPSRateLimiterAdapter.class, and DefaultBaseQqsAdapter.class respectively, and
add an assertEquals(expectedSize, allowedAdapters.size()) to verify the map size
for the whitelist contract.

---

Nitpick comments:
In
`@framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java`:
- Around line 33-87: Add two integration-style tests that exercise servlet
initialization rather than just the private whitelist map: 1) a happy-path test
that instantiates RateLimiterServlet, calls init(...) (using a Mock/Minimal
ServletConfig/ServletContext) with init-params that reference a known key such
as DEFAULT_BASE_QPS or QPS_RATE_LIMITER and then asserts that addRateContainer()
behavior occurred (e.g., the servlet exposes the configured container or a
non-null internal container/state after init); 2) a negative test that calls
init(...) with an unknown/invalid strategy name and asserts the servlet rejects
it (either by throwing ServletException or by leaving the rate-container
unregistered/null). Target the RateLimiterServlet.init(...) and
RateLimiterServlet.addRateContainer(...) code paths so the tests will fail if
init bypasses the ALLOWED_ADAPTERS whitelist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5b517087-2d82-4604-864c-0e57c5de76cb

📥 Commits

Reviewing files that changed from the base of the PR and between b5a05b8 and 9f2080f.

📒 Files selected for processing (4)
  • chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java
  • chainbase/src/main/java/org/tron/core/db/TransactionTrace.java
  • framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java
  • framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java

Comment on lines +304 to +305
long newUsage = newSize == 0 ? 0
: max(0, newArea / newSize, dynamicPropertiesStore.disableJavaLangMath());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify zero-size persistence and denominator usage paths.
rg -n -C2 --type=java \
'newUsage == 0 \? 0L : newSize|newUsage == 0 \? 0L : newSize2|divideCeil\(lastUsage \* this\.precision, oldWindowSize\)|divideCeil\(lastUsage \* precision, windowSize\)'

Repository: Sunny6889/java-tron

Length of output: 3476


🏁 Script executed:

#!/bin/bash
# Get divideCeil implementation to check for zero-handling
rg -A10 "^\s*long divideCeil\(" --type=java chainbase/src/main/java/org/tron/core/db/

Repository: Sunny6889/java-tron

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check for guards before divideCeil in ResourceProcessor.increase() method (lines 47-50)
sed -n '40,60p' chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java

Repository: Sunny6889/java-tron

Length of output: 1022


🏁 Script executed:

#!/bin/bash
# Check the full context of line 78-80 in ResourceProcessor
sed -n '70,90p' chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java

Repository: Sunny6889/java-tron

Length of output: 941


🏁 Script executed:

#!/bin/bash
# Check variables available at line 308 (currentSize context)
sed -n '290,310p' chainbase/src/main/java/org/tron/core/db/TransactionTrace.java

Repository: Sunny6889/java-tron

Length of output: 1127


🏁 Script executed:

#!/bin/bash
# Find divideCeil implementation
rg -B2 -A8 "private.*divideCeil|protected.*divideCeil|public.*divideCeil" --type=java chainbase/src/main/java/org/tron/core/db/

Repository: Sunny6889/java-tron

Length of output: 1117


🏁 Script executed:

#!/bin/bash
# Check V2 version around line 322
sed -n '310,340p' chainbase/src/main/java/org/tron/core/db/TransactionTrace.java

Repository: Sunny6889/java-tron

Length of output: 1392


🏁 Script executed:

#!/bin/bash
# Check for any guards before divideCeil calls in ResourceProcessor - full increase method
sed -n '73,85p' chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java

Repository: Sunny6889/java-tron

Length of output: 755


Persisted zero window sizes cause division by zero in ResourceProcessor.

The zero window size persistence at line 308 (newUsage == 0 ? 0L : newSize) and line 326 (newUsage == 0 ? 0L : newSize2) creates a critical issue. When ResourceProcessor.increase() retrieves the stored window size and calls divideCeil(lastUsage * precision, oldWindowSize) at line 78, a persisted zero will cause ArithmeticException: / by zero since divideCeil performs direct division without checking the denominator.

The available variables (currentSize at line 295, currentSize2 at line 313) enable the proposed fallback: persist a positive value (e.g., currentSize > 0 ? currentSize : 1L) when usage is zero, rather than persisting 0L.

Proposed fix
    accountCap.setEnergyUsage(newUsage);
-   accountCap.setNewWindowSize(ENERGY, newUsage == 0 ? 0L : newSize);
+   long persistedSize = newUsage == 0 ? (currentSize > 0 ? currentSize : 1L) : newSize;
+   accountCap.setNewWindowSize(ENERGY, persistedSize);

and

    accountCap.setEnergyUsage(newUsage);
-   accountCap.setNewWindowSizeV2(ENERGY, newUsage == 0 ? 0L : newSize2);
+   long persistedSize2 = newUsage == 0 ? (currentSize2 > 0 ? currentSize2 : 1L) : newSize2;
+   accountCap.setNewWindowSizeV2(ENERGY, persistedSize2);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@chainbase/src/main/java/org/tron/core/db/TransactionTrace.java` around lines
304 - 305, Persisted zero window sizes in TransactionTrace lead to
divide-by-zero later in ResourceProcessor.increase() when divideCeil(lastUsage *
precision, oldWindowSize) is called; modify the code that writes window sizes
(the expressions that set newUsage/newSize and newUsage/newSize2 in
TransactionTrace) so that when usage is zero you persist a positive fallback
(e.g., use currentSize > 0 ? currentSize : 1L and currentSize2 > 0 ?
currentSize2 : 1L) instead of 0L, ensuring divideCeil never receives a zero
denominator; update the logic around the newUsage computations to use these
non-zero fallbacks while keeping the existing semantics when usage is non-zero.

Comment on lines +43 to +58
public void testWhitelistContents() {
assertNotNull(allowedAdapters.get(GLOBAL_PREEMPTIBLE));
assertTrue(allowedAdapters.get(GLOBAL_PREEMPTIBLE)
.isAssignableFrom(GlobalPreemptibleAdapter.class));

assertNotNull(allowedAdapters.get(QPS_RATE_LIMITER));
assertTrue(allowedAdapters.get(QPS_RATE_LIMITER)
.isAssignableFrom(QpsRateLimiterAdapter.class));

assertNotNull(allowedAdapters.get(IP_QPS_RATE_LIMITER));
assertTrue(allowedAdapters.get(IP_QPS_RATE_LIMITER)
.isAssignableFrom(IPQPSRateLimiterAdapter.class));

assertNotNull(allowedAdapters.get(DEFAULT_BASE_QPS));
assertTrue(allowedAdapters.get(DEFAULT_BASE_QPS)
.isAssignableFrom(DefaultBaseQqsAdapter.class));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find framework -name "RateLimiterServletWhitelistTest.java" -type f

Repository: Sunny6889/java-tron

Length of output: 151


🏁 Script executed:

cat -n framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java

Repository: Sunny6889/java-tron

Length of output: 4556


🏁 Script executed:

# Check if the adapter classes exist
find framework -name "GlobalPreemptibleAdapter.class" -o -name "GlobalPreemptibleAdapter.java" | head -20

Repository: Sunny6889/java-tron

Length of output: 159


🏁 Script executed:

# Search for the adapter class definitions
rg "class GlobalPreemptibleAdapter|class QpsRateLimiterAdapter|class IPQPSRateLimiterAdapter|class DefaultBaseQqsAdapter" --type java

Repository: Sunny6889/java-tron

Length of output: 703


🏁 Script executed:

# Verify the current imports in the test file
head -25 framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java

Repository: Sunny6889/java-tron

Length of output: 1066


Use exact assertions for the whitelist contract.

The isAssignableFrom() checks are too permissive. If the map accidentally stored IRateLimiter.class instead of the specific adapter class, the test would still pass because IRateLimiter.class.isAssignableFrom(GlobalPreemptibleAdapter.class) returns true. Use assertSame() to enforce exact class identity, and use assertEquals() for the size comparison to provide clearer assertion semantics.

🧪 Tighten the assertions
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
@@
-    assertNotNull(allowedAdapters.get(GLOBAL_PREEMPTIBLE));
-    assertTrue(allowedAdapters.get(GLOBAL_PREEMPTIBLE)
-        .isAssignableFrom(GlobalPreemptibleAdapter.class));
+    assertSame(GlobalPreemptibleAdapter.class, allowedAdapters.get(GLOBAL_PREEMPTIBLE));
@@
-    assertNotNull(allowedAdapters.get(QPS_RATE_LIMITER));
-    assertTrue(allowedAdapters.get(QPS_RATE_LIMITER)
-        .isAssignableFrom(QpsRateLimiterAdapter.class));
+    assertSame(QpsRateLimiterAdapter.class, allowedAdapters.get(QPS_RATE_LIMITER));
@@
-    assertNotNull(allowedAdapters.get(IP_QPS_RATE_LIMITER));
-    assertTrue(allowedAdapters.get(IP_QPS_RATE_LIMITER)
-        .isAssignableFrom(IPQPSRateLimiterAdapter.class));
+    assertSame(IPQPSRateLimiterAdapter.class, allowedAdapters.get(IP_QPS_RATE_LIMITER));
@@
-    assertNotNull(allowedAdapters.get(DEFAULT_BASE_QPS));
-    assertTrue(allowedAdapters.get(DEFAULT_BASE_QPS)
-        .isAssignableFrom(DefaultBaseQqsAdapter.class));
+    assertSame(DefaultBaseQqsAdapter.class, allowedAdapters.get(DEFAULT_BASE_QPS));
@@
-    assertTrue("Whitelist must contain exactly 4 adapters", allowedAdapters.size() == 4);
+    assertEquals("Whitelist must contain exactly 4 adapters", 4, allowedAdapters.size());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@framework/src/test/java/org/tron/core/services/http/RateLimiterServletWhitelistTest.java`
around lines 43 - 58, The testWhitelistContents() assertions are too permissive:
replace the isAssignableFrom() checks on
allowedAdapters.get(GLOBAL_PREEMPTIBLE), get(QPS_RATE_LIMITER),
get(IP_QPS_RATE_LIMITER), and get(DEFAULT_BASE_QPS) with assertSame(...) against
the exact classes GlobalPreemptibleAdapter.class, QpsRateLimiterAdapter.class,
IPQPSRateLimiterAdapter.class, and DefaultBaseQqsAdapter.class respectively, and
add an assertEquals(expectedSize, allowedAdapters.size()) to verify the map size
for the whitelist contract.

@Sunny6889 Sunny6889 closed this Apr 2, 2026
@Sunny6889 Sunny6889 reopened this Apr 2, 2026
@Sunny6889 Sunny6889 requested a review from bladehan1 as a code owner April 2, 2026 09:04
@Sunny6889 Sunny6889 closed this Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants