Repository navigation
Merge main into protocol-next - #252
Merged
Merged
Conversation
) * internal/ingest/filters: match asset rules on ledger entry changes The asset ingestion filter matched rules against a fixed list of operation body fields. Any transaction that moved a whitelisted asset through a field outside that list was not ingested. The documented behaviour is that all transactions related to a whitelisted asset are retained. Cases that did not match before this change: - path payments where the whitelisted asset appears only in the Path array - claim and clawback of a claimable balance denominated in the asset - liquidity pool deposit and withdraw for a pool containing the asset - SetTrustLineFlags and AllowTrust on the asset - RevokeSponsorship of a trustline for the asset - Stellar Asset Contract transfers, mints, burns and clawbacks of the asset The filter now checks two sources and keeps the transaction on the first match: operation bodies, then ledger entry changes (trustline, offer, claimable balance, liquidity pool and Stellar Asset Contract balance entries). Operation bodies stay first because they are the only source for failed transactions. The asset filter now takes the network passphrase so it can derive the Stellar Asset Contract id for each whitelisted asset and match contract balance entries by that id. The admin API now validates each asset whitelist entry as a canonical CODE:ISSUER string and stores the canonical form. A malformed entry returns 400 instead of being stored and never matching. Operators running with an asset filter can re-run historical range ingestion to back-fill transactions skipped by earlier versions. Non-goals: CreateAccount and AccountMerge move only lumens and are not matched even when native is whitelisted. Stellar Asset Contract events are not read; contract activity is matched through the ledger entries it changes. Closes #11, closes #112. Addresses the asset half of #35. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * internal/ingest/filters: avoid shadowed err in AllowTrust test Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * internal/ingest/filters: read asset matches from raw meta and SAC ids - Match contract data entries on the Stellar Asset Contract id alone. This covers the native lumens contract and removes per-entry hashing. - Read ledger entry changes straight from the transaction meta, V0 to V4. GetChanges is no longer called, so the filter has no error path and no sort. - Store whitelist entries in canonical form when the filter loads them. - Share one whitelist parser between the filter and the admin API. - Add non-matching assertions for path payment, SetTrustLineFlags, RevokeSponsorship and claimable balance clawback. - Add tests for the native contract, a non-canonical stored entry, a malformed stored entry, and every meta version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * internal/ingest/filters: compare whitelisted assets by a map key The filter built the canonical string of every asset in every transaction to look it up in the whitelist. That encodes the issuer to strkey and allocates. The whitelist is now a map keyed by the 12-byte code and the issuer key. A lookup drops from about 175 ns and 3 allocations to about 7 ns and 0 allocations. - The key follows the canonical string rules: a 4-byte and a 12-byte code for the same letters give the same key. - A stored entry that does not parse still counts toward the whitelist size, so the filter stays enabled, as before. - TestAssetKeyAgreesWithCanonicalString checks that the key and the canonical string agree on equality. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * internal/ingest/filters: address Copilot review comments - Return meta change groups in the documented order: the changes before the operations, then each operation, then the changes after. - Test AllowTrust inside a fee-bump. The issuer comes from the inner transaction source, not the fee source. - Move the shared test constants to testutils_test.go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * internal/ingest/filters: address review comments on asset matching Matching: - Match InvokeHostFunction on the Stellar Asset Contract address and on a CreateContract from-asset preimage. A failed call has no operation meta, so the operation body is the only source. A native transfer between two G accounts changes only account entries, which are not read. - Match the Soroban footprint of the envelope. ExtendFootprintTTL and a pre-protocol-23 RestoreFootprint write only TTL entries to the meta. - Return an error on an unknown meta version instead of dropping silently. Admin API: - Keep a stored whitelist entry that does not parse, so a client can read the config, flip "enabled", and write it back. Reject only new entries. List every rejected entry in the response. - Return after rendering a database error in both update handlers. Perf: - Match fields in place instead of collecting []xdr.Asset per entry. Dropping a credit/credit offer that crosses three offers goes from 34 allocations and 1500 ns to 0 allocations and 256 ns. - matchMeta returns on the first match and allocates nothing. - Keep SAC ids in a set. Docs and tests: - CHANGELOG: claim, clawback, deposit and withdraw are kept only on success. Range reingest is safe only when the filter config has not changed since the range was first ingested. - Table-driven claim/clawback and SAC balance tests. Shared created() helper. Integration test uses MustCreateClaimableBalance. - Benchmark for the drop path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Brings in #230, #241, #246, #247, #248, #249, #250 and #251 from main. internal/ingest/core_lcm_test.go conflicted. #241 made filters.NewFilters take the network passphrase, and #237 moved the test code it changed into ingestCoreLCMFile, so the helper now passes coreTestNetworkPassphrase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MBWddBqppX2FsWGbuaJ82g
Shaptic
approved these changes
Oct 20, 2026
This was referenced Oct 20, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Syncs
protocol-nextwithmainbefore the Protocol 30 release. It brings in #230, #241, #246, #247, #248, #249, #250 and #251.There was one conflict, in
internal/ingest/core_lcm_test.go. #241 madefilters.NewFilterstake the network passphrase, and #237 moved the test code it changed intoingestCoreLCMFile, so the helper now passescoreTestNetworkPassphrase.Please merge with a merge commit, not squash, so
main's commits stay inprotocol-next's history and the release merge back intomainstays clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01MBWddBqppX2FsWGbuaJ82g