Skip to content

feat(random/unstable): allow generating seeded random bytes and 53-bit-entropy floats in [0, 1) (add getRandomValuesSeeded and nextFloat64) #6626

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 27, 2025

Conversation

lionel-rowe
Copy link
Contributor

@lionel-rowe lionel-rowe commented Apr 26, 2025

Towards #6602

Currently, this doesn't change the existing randomSeeded, other than a tiny documentation change to indicate that it only provides 32 bits of entropy.

Instead, it adds:

  • getRandomBytesSeeded, which returns a RandomValueGenerator function, fulfilling the same contract as crypto.getRandomBytes.
  • nextFloat64, which takes a RandomValueGenerator function and uses it to get a float in [0, 1) with 53 bits of entropy.

Used together, the two functions can be used to get identical f64 sequences to the rust rand crate, given the same u64 seed. getRandomBytesSeeded can also be used by reading little-endian from appropriately sized Uint8Arrays to get identical sequences of various integer types (u8, i32, etc.) to the rust crate.

There's still an open question as to whether the 32-bit-entropy randomSeeded should be superseded by the 53-bit-entropy version, and if so what the upgrade path looks like for that.

@lionel-rowe lionel-rowe requested a review from kt3k as a code owner April 26, 2025 10:45
Copy link

codecov bot commented Apr 26, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.71%. Comparing base (096f0be) to head (05d8bda).
Report is 38 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6626      +/-   ##
==========================================
- Coverage   94.74%   94.71%   -0.04%     
==========================================
  Files         583      567      -16     
  Lines       46478    46770     +292     
  Branches     6523     6578      +55     
==========================================
+ Hits        44036    44297     +261     
- Misses       2399     2431      +32     
+ Partials       43       42       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kt3k kt3k self-assigned this May 26, 2025
@kt3k
Copy link
Member

kt3k commented May 26, 2025

Sorry for the delay in review. Added functions seem fine to me.

Some feedbacks about the organization of code/API structures.

  • byteGeneratorSeeded, which returns a ByteGenerator function, fulfilling the same contract as crypto.getRandomBytes (sans the non-u8 typed array signatures, which are probably best avoided due to their unspecified endianness).
  • nextFloat64, which takes a ByteGenerator function and uses it to get a float in [0, 1) with 53 bits of entropy.

I think these 2 function should be exported from its own files (like ./byte_generateor_seeded.ts and ./next_float64.ts) to follow the general export rule of std.

byteGeneratorSeeded

I feel the name like randomBytesSeeded would be more aligned with the name of randomSeeded. What do you think?

* `crypto.getRandomValues`, i.e. taking a `Uint8Array` and mutating it by
* filling it with random bytes, returning the mutated `Uint8Array` instance.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
Copy link
Member

Choose a reason for hiding this comment

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

@experimental doc tag might be unnecessary for now as the entire package is still unstable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I just remove all those comments from @std/random then?

image

Copy link
Member

Choose a reason for hiding this comment

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

ah, then let's keep them.

assertEquals(actual, expected);
});
Deno.test("getRandomValues() writes bytes", () => {
const pgc = new Pcg32(0n);
Copy link
Member

Choose a reason for hiding this comment

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

nit: is pgc acronym intentional?

@lionel-rowe
Copy link
Contributor Author

I feel the name like randomBytesSeeded would be more aligned with the name of randomSeeded. What do you think?

Yeah maybe. It's modeled after crypto.getRandomValues, so the obvious would be getRandomValuesSeeded. The non-u8 signatures aren't currently supported, so getRandomBytesSeeded could work too.

Now I think about it, maybe the non-u8 signatures should be supported, via sniffing the platform endianness and filling bytes accordingly. That would make it fully viable as a stub for crypto.getRandomValues during testing (excluding marginal cases like passing a non-u8 typed array then reading byte-wise from its buffer).

@kt3k kt3k changed the title feat(random/unstable): allow generating seeded random bytes and 53-bit-entropy floats in [0, 1) feat(random/unstable): allow generating seeded random bytes and 53-bit-entropy floats in [0, 1) (add getRandomValuesSeeded and nextFloat64) May 27, 2025
Copy link
Member

@kt3k kt3k left a comment

Choose a reason for hiding this comment

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

Thanks for updating! LGTM

@kt3k kt3k merged commit f6e5cd3 into denoland:main May 27, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants