Skip to content

getLatestLedger: apply the same raw-bytes optimization that getLedgers already uses #731

Closed

Description

@urvisavla

Summary

getLedgers (via BatchGetLedgers in cmd/stellar-rpc/internal/db/ledger.go) avoids unmarshaling the full LedgerCloseMeta from the SQLite BLOB. It selects directly into [][]byte, keeps the raw bytes for base64 encoding, and parses only the small header prefix (V discriminator + optional LedgerCloseMetaExt + LedgerHeaderHistoryEntry). This bounds per-ledger XDR work to ~200 bytes regardless of the LCM size.

getLatestLedger doesn't follow this pattern. After #554 added the full LedgerMetadata field to its response, the handler now:

  1. Calls GetLedger → SQL scan into []xdr.LedgerCloseMeta, which triggers a full XDR Unmarshal of the entire BLOB (~2.8 MB on pubnet) into a deep struct tree.
  2. Calls latestLedger.MarshalBinary() → re-serializes that same struct tree back to bytes.
  3. Base64-encodes the result.

Steps 1 and 2 are wasted work — XDR encoding is canonical, so the bytes from the DB are byte-identical to the bytes we send in the response. The header fields we actually need (Hash, ProtocolVersion, LedgerCloseTime, the marshaled LedgerHeader) all live in the first ~200 bytes of the serialization.

Proposed fix

Apply the same raw-bytes pattern. Likely shape:

  • Add a new GetLedgerRaw(ctx, sequence) ([]byte, xdr.LedgerHeaderHistoryEntry, bool, error) method to LedgerReader — returns the raw BLOB plus the parsed header.
  • Factor the header-parsing logic out of BatchGetLedgers into a shared helper (e.g., parseLedgerHeaderFromMeta) so both BatchGetLedgers and GetLedgerRaw use the same parsing.
  • Update the getLatestLedger handler to call GetLedgerRaw, derive the response fields from the parsed header, and base64-encode the raw bytes directly without re-marshaling.

Metadata

Metadata

Assignees

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions