Add version-aware transaction size limits#1499
Add version-aware transaction size limits#1499mcintyre94 wants to merge 1 commit intotx-planner-constraintsfrom
Conversation
Increases the size limit to 4096 bytes for v1 transactions, while keeping the existing 1232-byte limit for legacy and v0. V1 is the first version to place the version byte first in the message bytes — earlier versions put signatures before the message, making the signature count the first byte. For compiled `Transaction` objects, version detection reads the first byte of `messageBytes` (the version byte in v1); for `TransactionMessage` objects it checks `message.version === 1`. Exports a new `getTransactionMessageSizeLimit` helper and `V1_TRANSACTION_SIZE_LIMIT` constant from `@solana/transactions`. Closes #1221.
🦋 Changeset detectedLatest commit: bc02a3f The changes in this PR will be included in the next version bump. This PR includes changesets to release 46 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
BundleMonFiles updated (16)
Unchanged files (126)
Total files change +2.66KB +0.55% Final result: ✅ View report in BundleMon website ➡️ |
|
Documentation Preview: https://kit-docs-ueel5oxoh-anza-tech.vercel.app |
lorisleiva
left a comment
There was a problem hiding this comment.
Nice! I made a couple of comments.
| export const TRANSACTION_SIZE_LIMIT = TRANSACTION_PACKET_SIZE - TRANSACTION_PACKET_HEADER; | ||
|
|
||
| /** | ||
| * The maximum size of a version 1 transaction in bytes. | ||
| */ | ||
| export const V1_TRANSACTION_SIZE_LIMIT = 4096; |
There was a problem hiding this comment.
I wonder if we should deprecate TRANSACTION_SIZE_LIMIT instead and not expose these constants. That way we ensure people go through the more accurate getTransactionMessageSizeLimit helper instead. Wdyt?
There was a problem hiding this comment.
That makes sense. I actually renamed TRANSACTION_SIZE_LIMIT at one point and then realised it was exported so I reverted that. Makes sense to deprecate that rather than exporting the new one.
| if (transaction.messageBytes.length === 0) { | ||
| // If there are no message bytes, then the transaction is empty and thus within the size limit. | ||
| return; | ||
| } | ||
|
|
||
| const firstByte = transaction.messageBytes[0]; | ||
| const sizeLimit = (firstByte & VERSION_FLAG_MASK) === 1 ? V1_TRANSACTION_SIZE_LIMIT : TRANSACTION_SIZE_LIMIT; |
There was a problem hiding this comment.
I'm not a big fan that we're having another location for computing the size limit for a transaction. I get that this is because the transaction message itself is compiled and encoded so we can't just defer to getTransactionMessageSizeLimit but maybe we should introduce a second getTransactionSizeLimit helper to make it clear that these two functions are the source of truth for that logic?

Problem
Currently we hardcode the transaction size limit to 1232 bytes. For v1 transactions this should be 4096 bytes.
Summary of Changes
Replace using constant transaction size limits with a function to get the size limit for a given
TransactionorTransactionMessage. ForTransactionMessagethis just reads theversionfield.For
Transactionwe use the fact that v1 transactions encode the version byte first, and the v1 value0x81is not a valid number of signatures for legacy/v0. Unlike the codec, we just need to know if it's v1 or not here to determine the answer, so we don't look at anything else. This will need to be extended for future versions, but assuming they put the version byte first it'll be trivial.Fixes: #1221