Add const XDR serialization - #580
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 550 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
fuzz/README.md:19
- This copyable command disables both leak detection and the RSS limit but does not bound the campaign, so the documented ~10 MB/s intentional leak will eventually exhaust memory. Add a finite run or time limit here as the paragraph below requires.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 550 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
fuzz/README.md:19
- This example omits the run/time bound that the paragraph below says is mandatory. Copied literally, cargo-fuzz uses libFuzzer's default unlimited run count, while these
Arbitraryimplementations intentionally leak, so the process will keep growing until interrupted or OOM. Please include a finite bound; for a one-pass corpus check, mirrormake fuzzwith-runs=0.
dmkozh
approved these changes
Sep 15, 2026
This was referenced Sep 21, 2026
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.
Tip
Reviewing Tips
I would focus a review of this change on two areas:
const::{Type}generated types to get an understanding for what code is being generated.ConstWritertype and the primitive XDR encoding methods.Note
Part of a stack of PRs listed here:
What
Add a
constfeature giving every generated type an alternative XDR encoding that can be used in const contexts. Add a static-lifetime borrowingconst::{Type}counterpart for every generated type that directly or transitively contains heap data.Why
The owned types require heap allocation to construct, so XDR values can't be built from borrowed slices inside const contexts. The const variant types can be constructed in const contexts.
XDR encoding is used by soroban-sdk to encode contract specs during proc-macro execution. The soroban-sdk will be changing when it encodes contracts specs to during compilation so that the specs can contain information only available during compile.
Known limitations
The
const::{Type}types are locked down only for use with borrowed data from static lifetimes, which isn't entirely necessary. An earlier implementation I did in #560 and #562 had these borrowed types as{Type}Ref<'a>where the lifetime was configurable and the type looked like it was useful as a ref type. However, in practice, because of the nature that these ref types get nested within arrays inside other ref types, they are not convertible to and from owned types and not really useful outside of a const static lifetime context. For that reason I've kept the types hyper focused on the immediate use case. If we ever have a use case for a more general ref variant of generated types we can reexplore #560.The const implementation is a separate implementation because a const implementation cannot use traits, which means it can't stream to a writer. It is not practical to maintain a single implementation that offers the same features of both. So instead there are two implementations and a test ensures they work identically.
I would have really liked to fuzz test the const xdr encoding with the existing xdr encoding, however I don't see a way to do that. We can't convert from owned to const types because of the way the const types are structured. Even if they were ref types with lifetimes we can't generate ref types from arbitrary because there would be nothing to own the values. Open to feedback on this, it's possible a slightly different way of architecting the ref types might make this possible.
Other Changes
I slipped a fix in here to the existing VecM, BytesM, StringM type Arbitrary implementations. All three could result in the types exceeding their max lengths. When I wrote the const variants of the types, they didn't have the same bug, and so I needed to fix the other for consistency.
I modified the
stellar-xdr generate arbitrarycli command so that it can accept entropy from a cargo-fuzz corpus file, which is a really helpful way to inspect and view what XDR values the corpus accepts.