feat(net): normalize inbound messages#6797
Open
halibobo1205 wants to merge 2 commits into
Open
Conversation
6cb7d58 to
656cb38
Compare
- BlockMessage strips Block and BlockHeader outer unknown fields and enforces the existing BLOCK_SIZE + ONE_THOUSAND cap before parsing. - TransactionMessage strips top-level transaction unknown fields and rejects oversized transactions with Manager.validateCommon-equivalent size checks after parsing. - TransactionsMessage strips wrapper and nested transaction top-level unknown fields and applies the same per-transaction size check to each entry.
656cb38 to
cdcceba
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Normalize inbound
BlockMessage/TransactionMessage/TransactionsMessageon rawbyte[]decode paths.Sanitize is applied only on the
byte[]constructors. Object-form constructors (BlockMessage(BlockCapsule),TransactionMessage(Transaction),TransactionsMessage(List<Transaction>)) intentionally keep existing behavior and preserve trusted local/store representations.What is sanitized
BlockMessage(byte[])Block.BlockHeader.BlockHeader.raw_data.TransactionMessage(byte[])Transaction.Transaction.raw_data.TransactionsMessage(byte[])Protocol.Transactions.Transaction.Transaction.raw_data.This keeps inbound wire representation normalized while leaving all consensus-hashed / signed regions byte-identical.
Size cap
Each inbound constructor applies the same size cap already enforced downstream, but earlier in the pipeline:
BlockMessage: rejects rawdata.length > BLOCK_SIZE + ONE_THOUSANDbefore protobuf parse.TransactionMessage: parses the tx first, then applies aManager.validateCommon-equivalent size check againstTRANSACTION_MAX_BYTE_SIZE(500 KB).TransactionsMessage: parses the wrapper first, then applies the same per-transaction size check to every nested tx.Performance note
The common no-unknown-fields path reuses the original inbound bytes when
parsed.getSerializedSize() == data.length, so sanitize does not rebuild or reserialize clean messages.For transaction messages, the size check still performs the same kind of
TransactionCapsule/ serialized-size work that previously happened inManager.validateCommon; this work is moved earlier so oversized padded txs are rejected before entering tx processing.Compatibility
TL;DR
BlockHeader.raw_dataorTransaction.raw_data.Throw site moved earlier
BlockMsgHandler.processMessage, after parseBlockMessage(byte[]), before parseManager.validateCommon, duringpushTransactionTransactionMessage(byte[])/TransactionsMessage(byte[]), after protobuf parse but before handler processingManager.validateCommon, viaWallet.broadcastTransaction -> pushTransactionTransactionMessage(byte[]), after protobuf parse but beforecheckExpiration/pushTransactionException type changes
P2pException(BAD_MESSAGE)P2pException(BAD_MESSAGE)(unchanged)TooBigTransactionExceptiondownstream, orP2pException(TRX_EXE_FAILED)afterTronNetDelegatewrappingP2pException(BAD_MESSAGE)from the message constructorDownstream effects:
Manager.validateCommonthrewTooBigTransactionException,TronNetDelegate.pushTransactionwrapped it asP2pException(TRX_EXE_FAILED), andTransactionsMsgHandlerlogged it without disconnecting the peer. After this PR, the constructor throwsP2pException(BAD_MESSAGE), which surfaces throughTronMessageFactory.createintoP2pEventHandlerImpl.processException;BAD_MESSAGEmaps toReasonCode.BAD_PROTOCOL, so the peer is disconnected. This aligns oversize tx handling with the existing oversize block behavior.Wallet.broadcastTransactioncatchesP2pException(BAD_MESSAGE)and maps it back toresponse_code.TOO_BIG_TRANSACTION_ERROR, so code-based callers keep the same response code. The response message string changes as described below.Exception detail strings
"block size over limit""block size over limit""Too big transaction..."Manager-format messages"transaction size over limit"For HTTP / gRPC oversize submissions,
response.coderemainsTOO_BIG_TRANSACTION_ERROR; onlyresponse.messagechanges. Callers that string-match on the old Manager-format text may need adjustment.Invalid compound payload ordering
Because oversized checks now happen earlier, invalid payloads that are both oversized and otherwise invalid may report the size error first. Examples:
TOO_BIG_TRANSACTION_ERRORbefore expiration is checked.TRXSpayloads are rejected during message construction before duplicate/no-request/contract-count checks.This only affects invalid oversized inputs. Normal, valid traffic is unchanged.
Log changes
BlockMsgHandlerno longer logs the block id for that case.P2pEventHandlerImpl.processException; because the message object was not constructed, the log may containmsg = null.Manager.validateCommon, so Manager's oldTooBigTransactionExceptionlogs do not fire for those inbound paths.Stored / rebroadcast representation
After this PR, inbound byte-decoded messages that contain targeted unknown fields are stored/rebroadcast without those unknown fields. Pre-upgrade nodes may keep the original padded wire bytes.
The logical identifiers are unchanged because sanitize does not touch
BlockHeader.raw_dataorTransaction.raw_data. During a rolling upgrade, nodes may temporarily have different on-disk byte representations for the same logical block/tx, but the block id / tx id and consensus behavior remain the same.