Skip to content

fix(rpc): count loaded accounts data size as SIMD-0186 does - #831

Merged
MicaiahReid merged 1 commit into
solana-foundation:mainfrom
L0STE:fix/loaded-accounts-data-size
Oct 5, 2026
Merged

MicaiahReid merged 1 commit into
solana-foundation:mainfrom
L0STE:fix/loaded-accounts-data-size

Conversation

@L0STE

@L0STE L0STE commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Problem

simulateTransaction computes loadedAccountsDataSize by hand, and it counts less than a validator
does. SIMD-0186, as Agave implements it in load_transaction_accounts
(svm/src/account_loader.rs), counts:

  • 64 bytes plus the data of every account the transaction loads, and nothing for one that does not
    exist;
  • a flat 8,248 bytes for every address lookup table, whatever it holds;
  • for a loader-v3 program, also 64 bytes plus its programdata, once, unless the transaction lists the
    programdata account itself.

Surfpool counts only the accounts' data, counts a lookup table's data instead of the flat size, and
counts programdata only for a program it has just fetched from the datasource. A program already on
the surfnet, including the ones bundled at startup, is counted without its programdata.

For example, a transfer to a new account resolved through a lookup table, which also passes an
upgradeable program with 1,000 bytes of programdata:

  1. A validator counts the payer (64), the system program (64 + 21), the program (64 + 36), its
    programdata (64 + 1,000) and the lookup table (8,248): 9,561 bytes.
  2. Surfpool reports 145: the system program's 21 bytes, the program's 36, and the lookup table's own
    88 bytes of data.

A client that sets setLoadedAccountsDataSizeLimit from the simulated size then sees the transaction
refused on chain with MaxLoadedAccountsDataSizeExceeded.

Fix

  • Every account counted also costs the 64-byte base. Each counted account is already recorded once
    in seen_accounts, so the base is added once for all of them.
  • Each address lookup table costs a flat 8,248 bytes. That also removes the second fetch of the
    lookup tables, which only existed to measure their data.
  • A loader-v3 program already on the surfnet also counts its programdata, the way a freshly fetched
    one already did.

The count is still Surfpool's own. A comment marks it for deletion once LiteSVM returns the size it
metered in TransactionMetadata (LiteSVM/litesvm#428), so the reported size and the metered size
come from one place. That PR also makes LiteSVM meter programdata, which it currently skips.

Test

  • test_simulate_transaction_loaded_accounts_data_size: an offline simulation with a payer, the
    system program, a missing recipient resolved through a lookup table, and an upgradeable program
    with its programdata. The expected size is written out account by account from the rules above.
  • test_simulate_add_alt_entries_fetching pinned 140,134, which depended on how much data a mainnet
    lookup table held and no longer matched. Under SIMD-0186 the table costs a flat size, so the value
    only depends on the table's first entry, the Token program, and on the Token program LiteSVM
    bundles. The breakdown is written next to the value.

Each test was checked by breaking the code one change at a time: dropping the base size, the lookup
table size or the programdata, charging the base for a missing account, and using the wrong base or
lookup table size. Every break turns at least one of them red.

Validation

  • cargo +nightly fmt --all -- --check
  • cargo clippy -p surfpool-core --all-targets adds no warnings
  • cargo test -p surfpool-core --lib -- loaded_accounts_data_size test_simulate_add_alt_entries_fetching
  • cargo test -p surfpool-core --lib: all pass, including test_simulate_add_alt_entries_fetching,
    which fails on main

@greptile-apps

greptile-apps Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Changes how transaction simulation counts account memory usage.

No new issue was identified in the PR patch since the previous review.

Summary

The PR updates simulateTransaction loaded-account sizing to include per-account overhead, flat address-lookup-table costs, and locally available programdata. It also updates the related size assertions. The current PR patch matches the patch at the previous review SHA; no new PR changes were identified.

Reviews (2) · Last reviewed commit: "fix(rpc): count loaded accounts data siz..."

MicaiahReid
MicaiahReid previously approved these changes Sep 30, 2026

@MicaiahReid MicaiahReid left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is great, good find!

@MicaiahReid
MicaiahReid merged commit ad8b13b into solana-foundation:main Oct 5, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants