Skip to content

Do not allow decoding transactions with an unsupported version#871

Merged
mcintyre94 merged 3 commits into
mainfrom
tx-version-unsupported
Sep 30, 2025
Merged

Do not allow decoding transactions with an unsupported version#871
mcintyre94 merged 3 commits into
mainfrom
tx-version-unsupported

Conversation

@mcintyre94
Copy link
Copy Markdown
Member

Problem

Kit currently supports codecs for legacy transactions, and transactions with version 0. There's currently a SIMD for transactions with version 1, which drastically changes how transactions are encoded. Kit will currently decode transactions claiming to have transaction message 1, but this decoding will be nonsense when such transactions exist.

Summary of Changes

We now throw a SolanaError when we decode a transaction and receive a version number greater than 0.

A future version of Kit will be able to add support for v1 transactions, while continuing to throw for still unsupported versions.

Fixes #866

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Sep 10, 2025

🦋 Changeset detected

Latest commit: 6e00621

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@solana/transaction-messages Patch
@solana/transactions Patch
@solana/errors Patch
@solana/instruction-plans Patch
@solana/kit Patch
@solana/programs Patch
@solana/rpc-api Patch
@solana/rpc-subscriptions-api Patch
@solana/signers Patch
@solana/transaction-confirmation Patch
@solana/compat Patch
@solana/react Patch
@solana/rpc-graphql Patch
@solana/accounts Patch
@solana/addresses Patch
@solana/assertions Patch
@solana/codecs-core Patch
@solana/codecs-data-structures Patch
@solana/codecs-numbers Patch
@solana/codecs-strings Patch
@solana/instructions Patch
@solana/keys Patch
@solana/options Patch
@solana/rpc-spec Patch
@solana/rpc-subscriptions-channel-websocket Patch
@solana/rpc-subscriptions-spec Patch
@solana/rpc-subscriptions Patch
@solana/rpc-transformers Patch
@solana/rpc-transport-http Patch
@solana/rpc-types Patch
@solana/rpc Patch
@solana/subscribable Patch
@solana/sysvars Patch
@solana/rpc-parsed-types Patch
@solana/codecs Patch
@solana/fast-stable-stringify Patch
@solana/functional Patch
@solana/nominal-types Patch
@solana/promises Patch
@solana/rpc-spec-types Patch
@solana/webcrypto-ed25519-polyfill Patch

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

@bundlemon
Copy link
Copy Markdown

bundlemon Bot commented Sep 10, 2025

BundleMon

Files updated (7)
Status Path Size Limits
transaction-messages/dist/index.native.mjs
7.25KB (+100B +1.37%) -
transaction-messages/dist/index.browser.mjs
7.25KB (+99B +1.35%) -
transaction-messages/dist/index.node.mjs
7.25KB (+99B +1.35%) -
@solana/kit production bundle
kit/dist/index.production.min.js
35.78KB (+76B +0.21%) -
errors/dist/index.browser.mjs
15.36KB (+72B +0.46%) -
errors/dist/index.native.mjs
15.36KB (+72B +0.46%) -
errors/dist/index.node.mjs
15.38KB (+72B +0.46%) -
Unchanged files (123)
Status Path Size Limits
rpc-graphql/dist/index.browser.mjs
18.82KB -
rpc-graphql/dist/index.native.mjs
18.81KB -
rpc-graphql/dist/index.node.mjs
18.81KB -
codecs-data-structures/dist/index.browser.mjs
4.69KB -
codecs-data-structures/dist/index.native.mjs
4.69KB -
codecs-data-structures/dist/index.node.mjs
4.69KB -
webcrypto-ed25519-polyfill/dist/index.node.mj
s
3.6KB -
webcrypto-ed25519-polyfill/dist/index.browser
.mjs
3.59KB -
webcrypto-ed25519-polyfill/dist/index.native.
mjs
3.57KB -
instruction-plans/dist/index.browser.mjs
3.42KB -
instruction-plans/dist/index.native.mjs
3.42KB -
instruction-plans/dist/index.node.mjs
3.41KB -
rpc-subscriptions/dist/index.browser.mjs
3.37KB -
rpc-subscriptions/dist/index.node.mjs
3.34KB -
rpc-subscriptions/dist/index.native.mjs
3.31KB -
codecs-core/dist/index.browser.mjs
3.31KB -
codecs-core/dist/index.native.mjs
3.31KB -
codecs-core/dist/index.node.mjs
3.31KB -
addresses/dist/index.browser.mjs
2.93KB -
rpc-transformers/dist/index.browser.mjs
2.93KB -
rpc-transformers/dist/index.native.mjs
2.93KB -
addresses/dist/index.native.mjs
2.93KB -
addresses/dist/index.node.mjs
2.93KB -
rpc-transformers/dist/index.node.mjs
2.93KB -
signers/dist/index.browser.mjs
2.63KB -
signers/dist/index.native.mjs
2.63KB -
signers/dist/index.node.mjs
2.62KB -
codecs-strings/dist/index.browser.mjs
2.53KB -
codecs-strings/dist/index.node.mjs
2.48KB -
codecs-strings/dist/index.native.mjs
2.45KB -
transaction-confirmation/dist/index.node.mjs
2.41KB -
transaction-confirmation/dist/index.native.mj
s
2.36KB -
transaction-confirmation/dist/index.browser.m
js
2.35KB -
sysvars/dist/index.browser.mjs
2.35KB -
sysvars/dist/index.native.mjs
2.34KB -
sysvars/dist/index.node.mjs
2.34KB -
transactions/dist/index.browser.mjs
2.31KB -
transactions/dist/index.native.mjs
2.31KB -
transactions/dist/index.node.mjs
2.3KB -
rpc-subscriptions-spec/dist/index.node.mjs
2.18KB -
rpc-subscriptions-spec/dist/index.native.mjs
2.13KB -
rpc-subscriptions-spec/dist/index.browser.mjs
2.13KB -
keys/dist/index.browser.mjs
2.08KB -
keys/dist/index.native.mjs
2.08KB -
keys/dist/index.node.mjs
2.08KB -
codecs-numbers/dist/index.native.mjs
2.01KB -
codecs-numbers/dist/index.browser.mjs
2.01KB -
codecs-numbers/dist/index.node.mjs
2.01KB -
react/dist/index.native.mjs
1.99KB -
react/dist/index.browser.mjs
1.99KB -
react/dist/index.node.mjs
1.99KB -
rpc/dist/index.node.mjs
1.95KB -
rpc-transport-http/dist/index.browser.mjs
1.91KB -
rpc-transport-http/dist/index.native.mjs
1.9KB -
rpc/dist/index.native.mjs
1.8KB -
subscribable/dist/index.node.mjs
1.8KB -
rpc/dist/index.browser.mjs
1.8KB -
subscribable/dist/index.native.mjs
1.75KB -
subscribable/dist/index.browser.mjs
1.74KB -
rpc-transport-http/dist/index.node.mjs
1.72KB -
kit/dist/index.browser.mjs
1.68KB -
kit/dist/index.native.mjs
1.68KB -
kit/dist/index.node.mjs
1.67KB -
rpc-types/dist/index.browser.mjs
1.53KB -
rpc-types/dist/index.native.mjs
1.53KB -
rpc-types/dist/index.node.mjs
1.53KB -
rpc-subscriptions-channel-websocket/dist/inde
x.node.mjs
1.33KB -
rpc-subscriptions-channel-websocket/dist/inde
x.native.mjs
1.27KB -
rpc-subscriptions-channel-websocket/dist/inde
x.browser.mjs
1.26KB -
options/dist/index.browser.mjs
1.18KB -
options/dist/index.native.mjs
1.18KB -
options/dist/index.node.mjs
1.17KB -
accounts/dist/index.browser.mjs
1.13KB -
accounts/dist/index.native.mjs
1.12KB -
accounts/dist/index.node.mjs
1.12KB -
rpc-api/dist/index.browser.mjs
976B -
rpc-api/dist/index.native.mjs
975B -
rpc-api/dist/index.node.mjs
973B -
compat/dist/index.browser.mjs
969B -
compat/dist/index.native.mjs
968B -
compat/dist/index.node.mjs
966B -
rpc-spec-types/dist/index.browser.mjs
962B -
rpc-spec-types/dist/index.native.mjs
961B -
rpc-spec-types/dist/index.node.mjs
959B -
rpc-subscriptions-api/dist/index.native.mjs
870B -
rpc-subscriptions-api/dist/index.node.mjs
869B -
rpc-subscriptions-api/dist/index.browser.mjs
868B -
rpc-spec/dist/index.browser.mjs
852B -
rpc-spec/dist/index.native.mjs
851B -
rpc-spec/dist/index.node.mjs
850B -
promises/dist/index.browser.mjs
799B -
promises/dist/index.native.mjs
798B -
promises/dist/index.node.mjs
797B -
assertions/dist/index.browser.mjs
783B -
instructions/dist/index.browser.mjs
769B -
instructions/dist/index.native.mjs
768B -
instructions/dist/index.node.mjs
767B -
fast-stable-stringify/dist/index.browser.mjs
726B -
fast-stable-stringify/dist/index.native.mjs
725B -
assertions/dist/index.native.mjs
724B -
fast-stable-stringify/dist/index.node.mjs
724B -
assertions/dist/index.node.mjs
723B -
programs/dist/index.browser.mjs
329B -
programs/dist/index.native.mjs
327B -
programs/dist/index.node.mjs
325B -
event-target-impl/dist/index.node.mjs
230B -
functional/dist/index.browser.mjs
154B -
functional/dist/index.native.mjs
152B -
text-encoding-impl/dist/index.native.mjs
152B -
functional/dist/index.node.mjs
151B -
codecs/dist/index.browser.mjs
137B -
codecs/dist/index.native.mjs
136B -
codecs/dist/index.node.mjs
134B -
event-target-impl/dist/index.browser.mjs
133B -
ws-impl/dist/index.node.mjs
131B -
text-encoding-impl/dist/index.browser.mjs
122B -
text-encoding-impl/dist/index.node.mjs
119B -
ws-impl/dist/index.browser.mjs
113B -
crypto-impl/dist/index.node.mjs
111B -
crypto-impl/dist/index.browser.mjs
109B -
rpc-parsed-types/dist/index.browser.mjs
66B -
rpc-parsed-types/dist/index.native.mjs
65B -
rpc-parsed-types/dist/index.node.mjs
63B -

Total files change +590B +0.16%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

Comment on lines +39 to +43
if (value > MAX_SUPPORTED_TRANSACTION_VERSION) {
throw new SolanaError(SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_NOT_SUPPORTED, {
unsupportedVersion: value,
});
}
Copy link
Copy Markdown
Member Author

@mcintyre94 mcintyre94 Sep 10, 2025

Choose a reason for hiding this comment

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

I've also disallowed encoding a TransactionVersion > 0, but I haven't added other checks for encoding because I don't think there's risk of accidentally encoding the wrong versions from Kit APIs, and we have a Typescript type for valid versions.

I mostly did this because I don't think it makes sense to have different supported/unsupported versions in the encode and decode tests.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Sep 10, 2025

Documentation Preview: https://kit-docs-2vu8exd9a-anza-tech.vercel.app

[SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE]:
'Transaction version must be in the range [0, 127]. `$actualVersion` given',
[SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_NOT_SUPPORTED]:
'This version of Kit does not support decoding transactions with version $unsupportedVersion. The current max supported version is 0.',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like this better than what I wrote in the offchain messages PR. I'm going to use this instead.

Comment on lines +243 to +251
if (
compiledTransactionMessage.version !== 'legacy' &&
compiledTransactionMessage.version > MAX_SUPPORTED_TRANSACTION_VERSION
) {
throw new SolanaError(SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_NOT_SUPPORTED, {
actualVersion: compiledTransactionMessage.version,
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this need to be here? If we:

  1. Hardcode 0 into the VersionedCompiledTransactionMessage type.
  2. Can't decode v1 transactions with the codec after this PR.

…then you should never be able to obtain one of these data structures, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think you're right, updated. The test I added for this is now a type error (version: 1) so I removed that test. But I think this is cleaner and it makes more sense to restrict the type there.

@mcintyre94 mcintyre94 force-pushed the tx-version-unsupported branch from ab69e7c to 154a047 Compare September 12, 2025 15:02
@mcintyre94 mcintyre94 force-pushed the tx-version-unsupported branch from 154a047 to defcbe9 Compare September 24, 2025 08:29
@mcintyre94 mcintyre94 force-pushed the tx-version-unsupported branch from defcbe9 to 6e00621 Compare September 30, 2025 08:27
@mcintyre94 mcintyre94 removed the request for review from lorisleiva September 30, 2025 08:27
@mcintyre94 mcintyre94 added this pull request to the merge queue Sep 30, 2025
Merged via the queue into main with commit cb11699 Sep 30, 2025
11 checks passed
@mcintyre94 mcintyre94 deleted the tx-version-unsupported branch September 30, 2025 08:28
@github-actions
Copy link
Copy Markdown
Contributor

Because there has been no activity on this PR for 14 days since it was merged, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Oct 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transaction / transaction message decoders must fail on unimplemented version

2 participants