Skip to content

SIMD-0287: Message Headers with Compute Budget Metadata #287

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 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions proposals/SIMD-03
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
simd: 0287
title: Message Headers with Compute Budget Metadata
authors:
- Cavey Cool
category: Standard
type: Interface
status: Idea/Review
created: 2025-05-20
feature: N/A
---

## Summary

We introduce three new (candidate) versions for transaction format aiming at
reducing the transaction footprint for compute budget instructions.

## Motivation

The use of compute budget instructions has become ubiquitous. These instructions
currently have a nontrivial serialized footprint and are presently wasteful in
their implementation. The information in these instructions can be compacted
significantly, enabling users to fit a bit more data in their transaction payload.

## Detailed Design

### v1: Fixed Fields for Compute Unit Limit & Price

- **Change**: `MessageHeader` is extended to include two new fields:
- `compute_unit_price` (u64)
- `compute_unit_limit` (u32)
- **Serialization**: These fields are serialized immediately before the existing
three `u8` signature counters.

### v2: Fixed Fields for Compute Unit Limit & Price, Loaded Data & Heap Requests

- **Change**: `MessageHeader` is extended to include four new fields:
- `compute_unit_price` (u64)
- `compute_unit_limit` (u32)
- `loaded_accounts_data_limit` (u32)
- `requested_heap_bytes` (u32)
- **Serialization**: These fields are serialized immediately before the existing
three `u8` signature counters.

### v3: Dynamic Header

- **Change**: Introduce a new `ComputeBudgetHeader` struct at the front of the
message, containing:
- `flags: u8` bitmask indicating which compute budget fields are present.
Copy link
Contributor

Choose a reason for hiding this comment

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

what're thoughts on the below? for future proof, is there a world where >8 compute-related operations take place?

#[repr(u8)]
enum ComputeBudgetOp {
    ComputeUnitPrice(u64),
    ComputeUnitLimit(u32),
    ...
}

ComputeBudgetHeader {
    // perhaps Vec encoded with u8 length discriminator instead of u64
    ops: Vec<ComputeBudgetOp>
}

Copy link
Author

Choose a reason for hiding this comment

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

image

Copy link
Author

Choose a reason for hiding this comment

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

in all seriousness, i think if we're worried about future proofing we can use a 16-bit flag

Copy link
Author

@cavemanloverboy cavemanloverboy May 21, 2025

Choose a reason for hiding this comment

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

this alternative repr is a bit wasteful bc every element comes with a discriminator, and you will need to check for dups. with the bitflag you get uniqueness for free and uniquely determines lenth + deserialization.

Copy link
Contributor

@buffalu buffalu May 21, 2025

Choose a reason for hiding this comment

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

edit: the optional fields confused me; thats for the API not for the serialization format. what you said makes sense to me

- Optional fields (`Option<u32>` or `Option<u64>`) for the parameters
- **Serialization**:
1. Emit `flags` byte.
2. For each bit set in `flags`, serialize the corresponding field in order
without additional tags.
3. Follow with the existing `MessageHeader` (three `u8` counters) and the
rest of the message.

## Alternatives Considered

I am proposing all options considered.

## Impact

- **DApp Developers**: Clients can still submit legacy/v0, but can opt in to the
new format to save some bytes.
- **Core Contributors**: Banking/Runtime must support parsing new versions.

## Security Considerations

- validators **MUST** reject messages with unknown budget `flags` bits (v3).

## Drawbacks

- Slight complexity in serializer/deserializer logic, particularly for v3.

## Backwards Compatibility

- `VersionedTransaction` has space in the variant discriminant to support these
versioned messsages.
Loading