Skip to content

Conversation

@tamirms
Copy link
Contributor

@tamirms tamirms commented Nov 7, 2025

PR Checklist

PR Structure

  • This PR has reasonably narrow scope (if not, break it down into smaller PRs).
  • This PR avoids mixing refactoring changes with feature changes (split into two PRs
    otherwise).
  • This PR's title starts with name of package that is most changed in the PR, ex.
    services/friendbot, or all or doc if the changes are broad or impact many
    packages.

Thoroughness

  • This PR adds tests for the most critical parts of the new functionality or fixes.
  • I've updated any docs (developer docs, .md
    files, etc... affected by this change). Take a look in the docs folder for a given service,
    like this one.

Release planning

  • I've reviewed the changes in this PR and if I consider them worthwhile for being mentioned on release notes then I have updated the relevant CHANGELOG.md within the component folder structure. For example, if I changed horizon, then I updated (services/horizon/CHANGELOG.md. I add a new line item describing the change and reference to this PR. If I don't update a CHANGELOG, I acknowledge this PR's change may not be mentioned in future release notes.
  • I've decided if this PR requires a new major/minor version according to
    semver, or if it's mainly a patch change. The PR is targeted at the next
    release branch if it's not a patch change.

What

Reduce memory consumption of state verification by discarding bucket entries corresponding to contract data, contract code, and config setting ledger entries which are ignored by horizon.

depends on stellar/go#5827

Why

Since eviction has been disabled we have observed a significant increase in memory consumption during state verification runs:

Screenshot 2025-10-23 at 10 18 56 AM

Prior to the SLP which disabled background eviction on oct 9 / 10, we had a peak memory consumption of 14-15 GB. Afterwards, the peak memory consumption reached upwards of 32 GB.

If the SLP is the root cause of the increased memory consumption that would imply that most of the ledger entries we are encountering while streaming from the history archives are contract data / contract code ledger entries which ordinarily would be evicted. But, horizon actually only ingests a tiny subset of contract data. In particular, horizon only cares about SAC contract data ledger entries.

This PR takes advantage of that fact by introducing a filter which discards any contract data ledger entries that are not likely SAC ledger entries. By doing so we have eliminated a significant amount of memory consumption:

Screenshot 2025-10-23 at 10 19 39 AM

Now, the peak memory consumption is 11-12 GB which is even less than what we observed before the SLP.

Known limitations

[N/A]

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the state verification logic by moving entry filtering from the StateVerifier's transform function to the history archive adapter level using the ingest.WithFilter option. The filtering logic for ConfigSetting, ContractCode, and ContractData entries is now applied at the source when reading from history archives, rather than during verification.

Key changes:

  • Removed the TransformLedgerEntryFunction type and related transform function logic from StateVerifier
  • Implemented filtering directly in historyArchiveAdapter.GetState() using ingest.WithFilter
  • Updated NewStateVerifier to remove the transform function parameter
  • Added network passphrase parameter to newHistoryArchiveAdapter to support filtering logic
  • Added deduplication logic in test helper generateRandomLedgerEntries to ensure unique ledger keys
  • Updated test cases to remove transform function tests and adjust constructor calls

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
internal/ingest/verify.go Removed TransformLedgerEntryFunction type and transform function logic; simplified StateVerifier constructor
internal/ingest/verify_test.go Removed transform function tests; updated constructor call; added deduplication logic for test data generation
internal/ingest/history_archive_adapter.go Added networkPassphrase parameter; implemented filtering using ingest.WithFilter
internal/ingest/history_archive_adapter_test.go Updated constructor call to include network passphrase
internal/ingest/main.go Updated constructor call to include network passphrase
internal/ingest/sample_changes_test.go Updated constructor call to include network passphrase
go.mod Updated stellar/go dependency version
go.sum Updated checksums for stellar/go dependency
Comments suppressed due to low confidence (1)

internal/ingest/verify.go:35

  • The StateVerifier documentation still references transformFunction which has been removed. This step should be removed or updated to reflect the new filtering approach where filters are applied at the history archive adapter level.
//  0. Develop `transformFunction`. It should remove all fields and objects not
//     stored in your app. For example, if you only store accounts, all other
//     ledger entry types should be ignored (return ignore = true).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tamirms tamirms requested review from a team and Copilot November 7, 2025 22:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@socket-security
Copy link

socket-security bot commented Nov 7, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedgithub.com/​stellar/​go@​v0.0.0-20251029182901-a312e7c16790 ⏵ v0.0.0-20251113110825-d9bbe0f8026975100100100100

View full report

Comment on lines 55 to 78
ledgerEntryFilter := func(ledgerEntry xdr.LedgerEntry) bool {
if ledgerEntry.Data.Type == xdr.LedgerEntryTypeConfigSetting ||
ledgerEntry.Data.Type == xdr.LedgerEntryTypeContractCode {
return false
}
if ledgerEntry.Data.Type == xdr.LedgerEntryTypeContractData {
_, assetFound := sac.AssetFromContractData(ledgerEntry, haa.networkPassphrase)
_, _, balanceFound := sac.ContractBalanceFromContractData(ledgerEntry, haa.networkPassphrase)
return assetFound || balanceFound
}
return true
}

ledgerKeyFilter := func(ledgerKey xdr.LedgerKey) bool {
if ledgerKey.Type == xdr.LedgerEntryTypeConfigSetting ||
ledgerKey.Type == xdr.LedgerEntryTypeContractCode {
return false
}
if ledgerKey.Type == xdr.LedgerEntryTypeContractData {
return sac.ValidContractBalanceLedgerKey(ledgerKey) ||
sac.ValidAssetEntryLedgerKey(ledgerKey)
}
return true
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have test coverage for this? If not, is it possible to add some?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

there is an integration test for state verification which should exercise this code. I just updated the state verification unit tests to invoke these filters

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.

3 participants