Skip to content

SIMD-0296: Increase Transaction Size Limit #296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
177 changes: 177 additions & 0 deletions proposals/0296-increase-tx-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
---
simd: '0296'
title: Increase Transaction Size
authors:
- jacobcreech
- apfitzge
category: Standard
type: Core
status: Review
created: 2025-05-28
feature: (fill in with feature key and github tracking issues once accepted)
---

## Summary

Historically, messages transmitted over the network must not exceed the IPc6 MTU
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Historically, messages transmitted over the network must not exceed the IPc6 MTU
Historically, messages transmitted over the network must not exceed the IPv6 MTU

Also worth noting the effective MTU is practically 1500 everywhere, not IPv6 MTU. Solana has just implemented an IPv6 recommendation incorrectly while using IPv4 only. Slightly lower (~20 ish bytes) for Double Zero on datacenters that don't support jumbo frames on the path between the user's host and the DZ gateway.

size to ensure a fast and reliable network delivery. Solana has used a
conservative MTU size of 1280 bytes, which after accounting for some of the
overhead, leaves a maximum transaction size of 1032 bytes for data in the
payload.

With QUIC, we can now use a larger transaction size than the original 1280
bytes. This proposal presents a new transaction size starting at 4096 bytes,
and the new v1 transaction format required to support the larger size. v1
transactions are a direct upgrade from the legacy format, while proposing
a removal of Address Lookup Tables compared to v0 transactions.

## Motivation

The current transaction size limit of 1232 bytes is too small for many
developer use cases. While there have been some attempts to artificially
increase the size capacity with address lookup tables, the current cap still is
artificially limiting the number of signatures and size of other data.

Use cases that are currently limited by the transaction size include:

- ZK proofs such as what is used within [Confidential
Balances](https://www.solana-program.com/docs/confidential-balances/zkps)
- Untruncated Winternitz one-time signatures
- Nested Multisig used by corporations under Squads
- Onchain cryptography signature schemes without precompiles such as BLS

and many more. A larger transaction size would also help remove the need for
address lookup tables, which have been a source of complexity on the validator
client as well as a frictional developer experience for many developers.

A number of developers have also resorted to using Jito bundles to artificially
increase the size of their transactions. This is a current workaround that
developers are using, but it does not have the same guarantees as a transaction
does on the protocol level, namely that bundles are not guaranteed to be atomic
like singular transactions.

For these reasons, increasing the current transaction size limit would enable
developers to create new applications and use cases that were previously
unfeasible.

## New Terminology

- 'v1 transaction' - A new transaction format that is designed to enable larger
transactions sizes while not having the address lookup table features
introduced in v0 transactions.

## Detailed Design

Increasing the transaction size limit above the current MTU max size is
possible with the use of QUIC. QUIC's RFC 9000 specification does not have an
explicit maximum stream size, allowing for larger transactions to be sent.

A new transaction format, `v1`, is proposed to enable larger transaction sizes.
The `v1` transaction format would be:

```
VersionByte (u8) - >127 to distinguish from legacy/v0 formats
LegacyHeader (u8, u8, u8) -- Required signatures from the current
`MessageHeader` type
Payload Length (u16) -- Total size excluding signatures
NumInstructions (u16)
ResourceRequestMask (u16) -- Bitmask of which resource requests are present.
For example bit 0 may mean "requested_cus", bit 1 may mean "microlamports per
cu"
NumStaticKeys (u8)
RecentBlockhash (hash)

Choose a reason for hiding this comment

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

Are we removing durable nonce support for v1 transactions?

Choose a reason for hiding this comment

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

If not, then rename this to LifetimeSpecifier.

Choose a reason for hiding this comment

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

As part of these discussions, it was proposed to get rid of nonce because it hits accountsdb, see https://github.com/solana-foundation/solana-improvement-documents/pull/296/files#r2129100914

Copy link
Contributor

Choose a reason for hiding this comment

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

We can't let noncery block this proposal. Rename it to LifetimeSpecficier seems fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm still in favor of removal of nonce support for v1 transactions. With v0 and legacy still coexisting with v1, this shouldn't be a blocker.

StaticKeys [[u8; 32]] -- Number matches NumStaticKeys
ResourceRequests [u64] -- Array of request values. (section size is popcount
ResourceRequestMask * 8). each value is a u64.
Ixs [(u16, u16, u16, u16)] -- Number matches NumInstructions. Values are
(num_accounts, accounts_offset, num_data_bytes, bytes_offset).
Copy link

@steveluscher steveluscher Jun 5, 2025

Choose a reason for hiding this comment

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

I presume that the accounts which are looked up in the TRAILING_DATA_SECTION are made up of (u8) indexes into the StaticKeys array above. If true, this design adds 2 bytes of data per account instruction over the existing design.

This SIMD (worst case):

  • u8 num ’static keys‘
  • [u8; 32] per ‘static key’
  • u16 num accounts per instruction
  • u16 num accounts offset per instruction
  • u8 index of account in the trailing data section per address per instruction

Fixed cost: 1 byte (num ‘static keys’)
Per instruction cost: 4 bytes (num accounts + accounts offset)
Per address cost: (32 + num_instructions) bytes (key + entry in TRAILING_DATA_SECTION per instruction)

Previously (worst case):

  • u8 num ‘static keys’
  • [u8; 32] per ‘static key’
  • compact-u16-array account indexes per address per instruction

Fixed cost: 1 byte (num ‘static keys’)
Per instruction cost: 2 bytes (compact-u16 index array length)
Per address cost: (32 + num_instructions) bytes (key + entry instruction's compact-u16 array)

Copy link
Contributor

Choose a reason for hiding this comment

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

It's unclear to me where you're getting 2 extra bytes per account. The design is definitely less space efficient, that's fine from our view since it's paired with a tx-size increase. It's better have constant sized fields than deal with compressed u16s inherent branchiness.

Choose a reason for hiding this comment

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

I said ‘per account’; meant ‘per instruction.’ Sorry.

[TRAILING DATA SECTION] -- Length is such that PayloadLength is matched.
Signatures [[u8; 64]] -- Length of `num_required_signatures` from
`LegacyHeader`
```

This new `v1` transaction format notably does not include address lookup
tables.

In consideration of what size the new transaction size limit should increase
to, [Jito's bundle

sizes](https://jitolabs.grafana.net/dashboard/snapshot/ISnwjbxw02UBLrj1xy4n4dFkAPyZ46ll?orgId=0&from=2025-05-30T18:45:00.000Z&to=2025-05-30T21:45:00.000Z&timezone=utc&var-cluster=mainnet&var-region=$__all&viewPanel=panel-40&inspect=panel-40&inspectTab=data)
that were used to increase the overall transaction size should be considered.
The following is the rough distribution of the transaction sizes:

- 2048 bytes or lower - 50% of bundles
- 6144 bytes or lower = 65% of all bundles
- 9216 bytes or lower = 100% of all bundles

In consideration of the above, the use cases mentioned within the motivation
section, and the current page size for managing memory within a validator, a
new transaction size limit of 4096 bytes is proposed. This new limit should
cover a majority of use cases mentioned within the motivation section, as well
as enable most of the developers using Jito bundles for larger transactions to
migrate to the new transaction format. Similarly, since the new limit proposed
can accomodate the max accounts used in ALTs directly in the transaction,
developers are able to migrate from `v0` transactions to `v1` transactions.

A number of changes are required to be made to the validator to support the new
transaction size limit. Consensus would need to be updated to support the
larger transaction size, as larger transactions included in a block would be
marked as invalid by the cluster today. The scheduler would also need to be
modified to support the larger transaction sizes. While this proposal does not
introduce a new fee structure around bytes in a transaction, the scheduler
should prioritize larger transactions differently, requiring developers to pay
a higher priority fee to land their transaction.

Testing for this new transaction size limit should be done extensively to
ensure that performance on the cluster is not adversely affected. This testing
should include the different use cases mentioned within the motivation section,
as well as the different sizes of transactions that are currently being used by
developers on the network.

## Alternatives Considered

Alternative designs considered:

- Having a transaction loading feature that would allow developers to load
the transaction parts in a buffer and then be able to execute them at the
end.
This method is no longer considered as it requires a much higher level of
latency on the application level and a decent amount of complexity within
the validator
- Bundles at the protocol level. This would not solve all problems that are
solved by larger transaction sizes. Bundles would still limit the ability for
developers to use cryptographic signature schemes that have large proof sizes.

## Impact

Developers would have to update with applications to use the new transaction
format to take advantage of the larger transaction size. Those developers that
had previously been using address lookup tables would be required to update the
new transactions with the full address list instead of the address lookup table
and its indices.

Over the long term, the new transaction format should require a migration to
fully deprecate both `legacy` and `v0` transaction formats, and in deprecating
`v0` transactions, the address lookup table feature would be removed from the
protocol.

## Security Considerations

Larger transaction sizes could results in a number of bandwidth issues on the
cluster than need to be tested thoroughly to ensure that performance is not
adversely affected.

## Drawbacks

There is an argument to be made that an increase in the transaction size limit
above the max MTU packet size would incur some network overhead due to
fragmentation retransmits. For a validator, this could mean maintaining
in-memory buffers for larger transactions compared to just receiving and
processing a single UDP packet. These issues will need to be addressed in the
scheduler and how priority fees for larger transactions are handled.

## Backwards Compatibility

As all of these changes are implemented with a new transaction format, the
increase on the transaction size limit does not affect or break `v0` or `legacy`
transactions.
Loading