Skip to content

feat(net): validate merkle root before block broadcast#6716

Open
xxo1shine wants to merge 1 commit intotronprotocol:developfrom
xxo1shine:fix/block-merkle-broadcast-and-sig-bypass-1
Open

feat(net): validate merkle root before block broadcast#6716
xxo1shine wants to merge 1 commit intotronprotocol:developfrom
xxo1shine:fix/block-merkle-broadcast-and-sig-bypass-1

Conversation

@xxo1shine
Copy link
Copy Markdown
Collaborator

What does this PR do?

  • Validate merkle root before block broadcast.
  • Reset isVerified on owner permission revocation.

Why are these changes required?

This PR has been tested by:

  • Unit Tests
  • Manual Testing

Follow up

Extra details

@github-actions github-actions Bot requested a review from 317787106 April 28, 2026 09:12
@halibobo1205 halibobo1205 added the topic:net p2p net work, synchronization label Apr 28, 2026
@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.2 milestone Apr 28, 2026
…fied on permission revocation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@xxo1shine xxo1shine force-pushed the fix/block-merkle-broadcast-and-sig-bypass-1 branch from d13259c to 193f361 Compare April 28, 2026 09:50
Comment on lines +350 to +354
try {
block.validateMerkleRoot();
} catch (BadBlockException e) {
throw new P2pException(TypeEnum.BLOCK_MERKLE_ERROR, e.getMessage());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice work moving the merkle check before broadcast — that's exactly the right place to catch tampered blocks before we forward them. 🎯

Minor consistency nit: when wrapping BadBlockException here, you're passing e.getMessage() as the message string, but the existing flow in processBlock (around L302) wraps it as throw new P2pException(TypeEnum.BLOCK_MERKLE_ERROR, e) (the exception itself becomes the cause). Would it make sense to do the same here so the original stack trace is preserved when this propagates up? It also keeps the two BLOCK_MERKLE_ERROR throw sites symmetric.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The BLOCK_MERKLE_ERROR exception is quite obvious, and the message information is sufficient. There's no need to re-throw the original exception, and the previous logic doesn't need to be changed; there's no impact whatsoever.

@lvs0075 lvs0075 requested a review from waynercheung April 30, 2026 03:48
if (ownerAddressSet.contains(ownerAddress)) {
tx.setVerified(false);
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[INT] Give code comment why should setVerified as false here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This if statement is already quite concise and clear. Transactions involving permission changes should reset this flag. Re-verification is required to prevent transactions with incorrect signatures from entering the pending queue.

import org.tron.core.capsule.utils.MerkleTree;
import org.tron.core.config.Parameter.ChainConstant;
import org.tron.core.exception.BadBlockException;
import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SHOULD] Static import is interleaved with regular imports. Move it above all import org... lines as a separate group, matching the convention used in TronNetDelegate.java:4 and ManagerTest.java:11. Likely a Checkstyle violation.

Assert.assertEquals(TronError.ErrCode.EVENT_SUBSCRIBE_ERROR, thrown.getErrCode());
}

@Test
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SHOULD] The PR title is "validate merkle root before block broadcast", but TronNetDelegate.validBlock() - the function that actually realises this - has no direct test. Consider adding a test that constructs a block with a tampered merkle root and asserts validBlock throws P2pException with TypeEnum.BLOCK_MERKLE_ERROR. The existing tests only cover BlockCapsule.validateMerkleRoot() and the Manager.pushBlock path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:net p2p net work, synchronization

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

7 participants