Skip to content

zk-sdk: Do not require passing owned vectors to RangeProof - #194

Merged
joncinque merged 3 commits into
solana-program:mainfrom
vadorovsky:zk-sdk-avoid-heap-alloc
Sep 22, 2026
Merged

joncinque merged 3 commits into
solana-program:mainfrom
vadorovsky:zk-sdk-avoid-heap-alloc

Conversation

@vadorovsky

Copy link
Copy Markdown
Member

The current implementation of RangeProof::new and RangeProof::verify requires the caller to pass inputs as owned vectors. That requires heap allocations even if the number of inputs is small (even as small as 1).

Remove that requirement by accepting AsRef<[T]> trait as inputs, which still makes it possible to pass Vec<T>, so we don't break the old users relying on the old API. But for callers who want performance, it accepts also the following types that can be allocated on the stack:

  • [T]
  • [T; N]
  • &[T]

Furthermore, single elements can be passed using slice::from_ref[0], e.g.

let proof = RangeProof::new(
    slice::from_ref(&55),
    slice::from_ref(&64),
    slice::from_ref(&open),
    &mut transcript_create,
)

which does not perform any allocation at all. Instead, it performs raw pointer casting to coerce a reference to a single-element slice[1][2].

Additionally, AsRef<T> makes it possible to pass the following iterable types:

  • std::slice::Iter<'_, T>
  • IterMut<'_, T>
  • IntoIter<T, A>

[0] https://doc.rust-lang.org/std/slice/fn.from_ref.html
[1] https://github.com/rust-lang/rust/blob/1.92.0/library/core/src/slice/raw.rs#L203-L205
[2] https://github.com/rust-lang/rust/blob/1.92.0/library/core/src/array/mod.rs#L164-L167

@vadorovsky
vadorovsky marked this pull request as ready for review January 14, 2026 12:53
@samkim-crypto
samkim-crypto self-requested a review January 14, 2026 13:28
@samkim-crypto
samkim-crypto force-pushed the zk-sdk-avoid-heap-alloc branch from 06f7d8d to 2ba9891 Compare September 16, 2026 13:23
@samkim-crypto

Copy link
Copy Markdown
Contributor

@vadorovsky I rebased the changes onto main, cleaned up the lint issues, and added a few compatibility and validation tests for sanity. Let me know if I made any mistakes!

samkim-crypto
samkim-crypto previously approved these changes Sep 17, 2026
Rchie121

This comment was marked as spam.

@vadorovsky vadorovsky left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@samkim-crypto Your changes look good. Feel free to merge it.

@samkim-crypto

Copy link
Copy Markdown
Contributor

@joncinque since I was the last committer, I can't seem to approve and merge this PR. Can you give an approval for this PR 🙏 ?

joncinque
joncinque previously approved these changes Sep 22, 2026

@joncinque joncinque left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me! But needs a merge conflict resolution

vadorovsky and others added 3 commits September 22, 2026 22:41
The current implementation of `RangeProof::new` and `RangeProof::verify`
requires the caller to pass inputs as owned vectors. That requires heap
allocations even if the number of inputs is small (even as small as 1).

Remove that requirement by accepting `AsRef<[T]>` trait as inputs, which
still makes it possible to pass `Vec<T>`, so we don't break the old
users relying on the old API. But for callers who want performance, it
accepts also the following types that can be allocated on the stack:

- `[T]`
- `[T; N]`
- `&[T]`

Furthermore, single elements can be passed using `slice::from_ref`[0],
e.g.

```rust
let proof = RangeProof::new(
    slice::from_ref(&55),
    slice::from_ref(&64),
    slice::from_ref(&open),
    &mut transcript_create,
)
```

which does not perform any allocation at all. Instead, it performs raw
pointer casting to coerce a reference to a single-element slice[1][2].

Additionally, `AsRef<T>` makes it possible to pass the following
iterable types:

- `std::slice::Iter<'_, T>`
- `IterMut<'_, T>`
- `IntoIter<T, A>`

[0] https://doc.rust-lang.org/std/slice/fn.from_ref.html
[1] https://github.com/rust-lang/rust/blob/1.92.0/library/core/src/slice/raw.rs#L203-L205
[2] https://github.com/rust-lang/rust/blob/1.92.0/library/core/src/array/mod.rs#L164-L167
@samkim-crypto
samkim-crypto dismissed stale reviews from joncinque and themself via 4222a1a September 22, 2026 13:44
@samkim-crypto
samkim-crypto force-pushed the zk-sdk-avoid-heap-alloc branch from 2ba9891 to 4222a1a Compare September 22, 2026 13:44

@vadorovsky vadorovsky left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't have a right to approve, but ship it :shipit:

@joncinque
joncinque merged commit a0d563c into solana-program:main Sep 22, 2026
27 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.

4 participants