refactor(pq): remove redundant PQ guards and add pending pool pre-checks#41
refactor(pq): remove redundant PQ guards and add pending pool pre-checks#41bladehan1 wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughPQ signature validation now runs without a global activation pre-check in transaction and block code. Wallet and Manager now reject shielded and PQ transactions when pending pools are full, with tests covering the new ChangesPQ signature validation
Pending queue capacity
Sequence Diagram(s)sequenceDiagram
participant Client
participant Wallet
participant Manager
Client->>Wallet: broadcastTransaction(transaction)
alt shielded pending pool is full
Wallet->>Manager: isShieldedPendingFull(transaction)
Manager-->>Wallet: true
Wallet-->>Client: response_code.SERVER_BUSY "Shielded pending pool is full"
else PQ pending pool is full
Wallet->>Manager: isPqPendingFull(transaction)
Manager-->>Wallet: true
Wallet-->>Client: response_code.SERVER_BUSY "PQ pending pool is full"
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java (1)
499-503: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRemove the remaining global PQ activation pre-check.
This relaxed condition is still shadowed by
validatePubSignatureLines 669-673, so normaltrx.validateSignature(...)callers can still fail onisAnyPqSchemeAllowed()before reaching the per-scheme checks here.Proposed fix
- if (this.transaction.getPqAuthSigCount() > 0 && - !dynamicPropertiesStore.isAnyPqSchemeAllowed()) { - throw new ValidateSignatureException( - "pq_auth_sig not allowed: no post-quantum scheme is activated"); - } int signatureCount = getTotalSignatureCount();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java` around lines 499 - 503, The remaining global PQ activation pre-check in TransactionCapsule still blocks normal trx.validateSignature(...) flows before the per-scheme logic runs. Remove the isAnyPqSchemeAllowed() gating from the PQ path in TransactionCapsule.validateSignature/validatePubSignature and rely on the specific PQ scheme checks inside validatePQSignatureGetWeight and the existing per-signature validation branches so callers can reach the intended scheme-specific handling.
🧹 Nitpick comments (1)
framework/src/main/java/org/tron/core/db/Manager.java (1)
931-943: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider reusing the new predicates inside
pushTransaction.The inline shielded/PQ pending-full conditions here duplicate
isShieldedPendingFull(trx.getInstance())/isPqPendingFull(trx.getInstance()). Reusing them keeps the “full” definition in one place (the warn logging can stay inline). Optional given the inline logging needs the counter values.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@framework/src/main/java/org/tron/core/db/Manager.java` around lines 931 - 943, The pending-pool full checks inside pushTransaction duplicate the logic already centralized in isShieldedPendingFull and isPqPendingFull. Update the guard conditions in Manager.pushTransaction to call those predicates instead of rechecking the counters inline, while keeping the existing warn logs inline so the counter values remain available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@framework/src/main/java/org/tron/core/db/Manager.java`:
- Around line 2184-2192: `isShieldedTransaction` should guard against empty
contract lists before reading the first contract, since `isShieldedPendingFull`
calls it directly and can trigger an `IndexOutOfBoundsException` on transactions
with no contracts. Update `Manager.isShieldedTransaction` to check
`transaction.getRawData().getContractList().isEmpty()` and return false before
accessing `getContract(0)`, keeping the existing shielded transaction logic
unchanged for non-empty transactions.
In `@framework/src/main/java/org/tron/core/Wallet.java`:
- Around line 581-591: The shielded/PQ pending-full checks in
Wallet.broadcastTransaction are running before the contract-count validation,
which can trigger an IndexOutOfBoundsException via
dbManager.isShieldedPendingFull or dbManager.isPqPendingFull on empty-contract
transactions. Move both checks to after the contract-size guard in
broadcastTransaction, but still before pushTransaction, so the transaction is
known to have at least one contract and the existing CONTRACT_VALIDATE_ERROR
path is preserved.
---
Outside diff comments:
In `@chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java`:
- Around line 499-503: The remaining global PQ activation pre-check in
TransactionCapsule still blocks normal trx.validateSignature(...) flows before
the per-scheme logic runs. Remove the isAnyPqSchemeAllowed() gating from the PQ
path in TransactionCapsule.validateSignature/validatePubSignature and rely on
the specific PQ scheme checks inside validatePQSignatureGetWeight and the
existing per-signature validation branches so callers can reach the intended
scheme-specific handling.
---
Nitpick comments:
In `@framework/src/main/java/org/tron/core/db/Manager.java`:
- Around line 931-943: The pending-pool full checks inside pushTransaction
duplicate the logic already centralized in isShieldedPendingFull and
isPqPendingFull. Update the guard conditions in Manager.pushTransaction to call
those predicates instead of rechecking the counters inline, while keeping the
existing warn logs inline so the counter values remain available.
🪄 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: 387b5842-4db1-4713-85b8-b53f0a31a8fe
📒 Files selected for processing (7)
actuator/src/main/java/org/tron/core/utils/TransactionUtil.javachainbase/src/main/java/org/tron/core/capsule/BlockCapsule.javachainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.javaframework/src/main/java/org/tron/core/Wallet.javaframework/src/main/java/org/tron/core/db/Manager.javaframework/src/test/java/org/tron/core/WalletMockTest.javaframework/src/test/java/org/tron/core/db/ManagerMockTest.java
💤 Files with no reviewable changes (2)
- chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java
- actuator/src/main/java/org/tron/core/utils/TransactionUtil.java
There was a problem hiding this comment.
1 issue found across 7 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
5ac1aa4 to
4fb3689
Compare
db3bd7b to
37d8a56
Compare
37d8a56 to
8d214aa
Compare
What does this PR do?
TransactionCapsule.validatePubSignature: Remove&& isAnyPqSchemeAllowed()from line 499. The old code skipped PQ validation entirely when no PQ scheme was activated, so any transaction carrying arbitrary forgedpq_auth_sigentries would silently pass using ECDSA weight alone. After this change, every transaction withpq_auth_sigentries is always validated — when the scheme is disabled, the innerisPqSchemeAllowed(scheme)check correctly rejects it. This is a behavior change (accept → reject), not a refactor.BlockCapsule.validateSignatureandTransactionUtil.checkPermission: In these two paths the outerisAnyPqSchemeAllowed()guard was truly redundant — both old and new code reject when PQ is disabled (only the exception message changes from generic to scheme-specific).validatePQSignatureGetWeight: replace the manual for-loop withstream().filter().findFirst().orElseThrow(...), preserving identical semantics.logger.warninManager.pushTransactionfor the PQ pending pool full branch (txId, current count, limit).Manager.isPqPendingFulland wire it as an early pre-check inWallet.broadcastTransaction(after the existingisTooManyPending()check), returningSERVER_BUSYwith"PQ pending pool is full."beforepushTransactionis called. This fixes the silentSUCCESSpreviously returned when the PQ pending pool was full.Why are these changes required?
TransactionCapsule:499): The old outer guardisAnyPqSchemeAllowed()short-circuited before validating PQ signatures when PQ was globally disabled. An attacker could append arbitrarypq_auth_sigentries to any transaction that already carried a valid ECDSA signature; those entries were silently ignored, and the transaction passed weight validation with ECDSA alone. Removing the outer guard ensures everypq_auth_sigentry is always validated, regardless of activation state.BlockCapsule,TransactionUtil): In both locations, the outer guard threw an exception identical in effect to what the inner per-scheme check would throw anyway. Removing them simplifies the rejection path and makes error messages scheme-specific.SUCCESS; the fix adds an explicit earlySERVER_BUSYresponse and an actionable warn log.This PR has been tested by:
TransactionCapsuleTest.pqKeyNotInPermissionThrows— streamorElseThrowpath: signer not in permission →PermissionExceptionTransactionCapsuleTest.pqKeyFoundReturnsWeight— stream happy path: key found → correct weight returnedTransactionCapsuleTest.pqWrongKeyLengthThrows— pk/sig length mismatch →SignatureFormatExceptionTransactionCapsuleTest.pqWeightOverflowThrows— twoLong.MAX_VALUEweights →PermissionException("weight overflow")ManagerMockTest.testPushTransactionPqPendingFull— PQ pool full →pushTransactionreturnsfalse+ warn logWalletMockTest.testBroadcastTransactionPqPendingFull— PQ pool full →SERVER_BUSYwith "PQ" in message,pushTransactionnever calledBlockCapsulePQTest,TransactionCapsuleTest,TransactionUtilTest— existing tests passFollow up
BlockCapsule,TransactionUtil): the old generic string"pq_auth_sig not allowed: no post-quantum scheme is activated"is replaced by scheme-specific text. Downstream monitoring rules matching the old string will need updating.isVerifiedcache interaction with proposal "enable-then-disable" is a known scope-out; tracked separately.Extra details
.protochanges, no newresponse_codevalues, no config changes.