Skip to content

refactor(trie): remove unused RLP utilities - #21

Open
Sunny6889 wants to merge 1 commit into
Sunny6889:developfrom
Little-Peony:clean_rlp
Open

refactor(trie): remove unused RLP utilities#21
Sunny6889 wants to merge 1 commit into
Sunny6889:developfrom
Little-Peony:clean_rlp

Conversation

@Sunny6889

Copy link
Copy Markdown
Owner

What does this PR do?

Removes the RLP utilities under framework/src/main/java/org/tron/core/capsule/utils that nothing calls, and reduces the one that is still needed to the part that is actually used.

RLP (Recursive Length Prefix) is Ethereum's serialization format. It arrived with the original ethereumJ fork; TRON serializes its own transactions, blocks and accounts with protobuf, so RLP has no place in consensus or state. The only remaining consumer is org.tron.core.trie.TrieImpl, which needs it because the trie node layout it implements is defined in terms of RLP-encoded lists.

  • Deletes six files with no main-code references: RLPElement, RLPItem, RLPList, DecodeResult (reachable only from the removed RLP methods), and TxInputUtil / TxOutputUtil (leftovers from the UTXO-era code), plus their four tests.
  • Trims RLP.java from 1216 lines to 284. TrieImpl uses four entry points out of 34 public methods; taking the reachability closure from those leaves six constants, decodeLazyList, verifyLength, both encodeList overloads and the nested LList. The other 30 methods go.
  • Drops the duplicate FastByteComparisons. org.tron.common.utils.FastByteComparisons already exists and is what nine other files use; the copy under capsule/utils had two consumers. TrieImpl now calls the common one.

capsule/utils goes from eight files to one. 15 files changed, +52 / −1509.

Why are these changes required?

Most of this code has never had a caller in TRON. Carrying a full RLP codec — a second serialization format, in a package named for capsule utilities — costs review attention on every audit, keeps test surface alive for code that cannot run, and blurs where the trie's dependencies actually begin.

Behaviour: unchanged.

The change is a deletion, not a rewrite. Two properties were checked rather than assumed:

  • Everything kept in RLP.java is byte-identical to the previous version. The parameter lists and bodies of all nine retained methods (including all four overloads) and the values of the six retained constants were compared against the pre-change file; none was rewritten. The encoder therefore produces the same bytes, and account-state root hashes cannot move.
  • The two FastByteComparisons are the same implementation. Normalising away package, imports and the method name (equalByte vs isEqual), the two files are identical, comparer holder included. This matters because TrieImpl uses it to compare root hashes.

The trie itself sits behind allowAccountStateRoot, which defaults to 0 and has never been enabled on mainnet — but it still runs when the flag is on, which is why the change had to be equivalence-preserving rather than merely compiling.

This PR has been tested by:

  • Unit Tests — all passing:
    • TrieTest (7) — the trie's own behaviour test, including root-hash order independence and proof verification.
    • ManagerTest (36) and HistoryBlockHashIntegrationTest (16) — cover the AccountStateCallBack / AccountStateStoreTrie path that reaches RLP.
    • SupplementTest (3) — the coverage test that called the removed decode methods.
    • ./gradlew :framework:checkstyleMain :framework:checkstyleTest.
  • Manual Testing — not applicable: no runtime path changes, and the only consumer is gated off by default.

Follow up

org.tron.core.trie and the accountStateRoot machinery above it are deliberately out of scope. Removing them would touch Manager, ChainBaseManager and the DB stores, which is a different risk class, and the historical-state work under design covers the same area — this PR leaves that decision open rather than pre-empting it.

Extra details

Two things worth knowing for review:

  • Both encodeList overloads are needed. TrieImpl passes Object[] (Node.children, hashArray), which binds encodeList(Object...); the retained LList.getEncoded() passes byte[][], which binds encodeList(byte[]...). Keeping only one changes which method the trie calls.
  • TrieTest used RLP.encodeInt only to build keys, but not any replacement works. Line 49 puts new byte[]{1} and the next line reads it back; encodeInt(1) returns the single byte [1], which is what made that pair match. It is now ByteUtil.intToBytesNoLeadZeroes, whose output is identical to RLP.encodeInt for every key the test uses (all in 1..111), so the keys — and the root hashes asserted from them — are unchanged.

@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 546cab0b-ef1e-42da-b720-72a43febce8d


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.

@Sunny6889 Sunny6889 changed the title refactor(trie): keep only the rlp code the trie uses refactor(trie): remove unused rlp utilities Sep 3, 2026
@Sunny6889 Sunny6889 changed the title refactor(trie): remove unused rlp utilities refactor(trie): remove unused RLP utilities Sep 3, 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