fix(rust-client): replace RandomCoin with ChaCha20Rng - #2414
Conversation
…ects a non-CryptoRng
RandomCoinRandomCoin with ChaCha20Rng
juan518munoz
left a comment
There was a problem hiding this comment.
Looks good overall. What I still don't understand is why we are keeping rng and secure_rng separately, for what I see we could just get away with the new secure implementation in all places.
If I'm not mistaken, keeping a single rng would also make the trybuild test redundant.
| /// the field modulus, which keeps the result uniform over the field. The rejection | ||
| /// probability is about 2^-32. | ||
| pub fn draw_felt(rng: &mut impl rand::Rng) -> crate::Felt { | ||
| use rand::RngExt; |
There was a problem hiding this comment.
we should move the import outside this function
| /// Uses rejection sampling: [`Felt::new`](crate::Felt::new) rejects any `u64` at or beyond | ||
| /// the field modulus, which keeps the result uniform over the field. The rejection | ||
| /// probability is about 2^-32. | ||
| pub fn draw_felt(rng: &mut impl rand::Rng) -> crate::Felt { |
There was a problem hiding this comment.
Maybe this functions are better suited in a separate file, similar to how we do with utils.rs, we could add an rng.rs file.
| /// | ||
| /// Use this for note serial numbers when building notes from a plain [`rand`] generator, which | ||
| /// does not implement [`FeltRng`]. | ||
| pub fn draw_word(rng: &mut impl rand::Rng) -> crate::Word { |
|
@juan518munoz thanks! all comments were addressed in this commit e3b4748.
We keep both |
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| /// Checks that [`ClientBuilder::rng`] rejects a generator that is not a `CryptoRng`. |
There was a problem hiding this comment.
this is already enforced by the compiler in the type system, we can remove this test IMO
There was a problem hiding this comment.
If we remove the test, then we should remove this file
juan518munoz
left a comment
There was a problem hiding this comment.
LGTM. Before merging this, it may be a good idea to create a branch on web-sdk that points to this branch, so we can assure there won't be any setbacks.
|
@juan518munoz I created a draft PR in the |
huitseeker
left a comment
There was a problem hiding this comment.
Thanks for taking this on. Replacing RandomCoin with a standard CryptoRng is the right direction.
I checked the web SDK compatibility PR to understand why the client accepts a seed. Account recovery already has a separate path: newWallet(initSeed) derives the account key and initialization seed, while importPublicAccountFromSeed repeats that derivation. This path does not need ClientBuilder::rng.
The seed passed to createClient has a wider effect. It controls the client's operational RNG and also derives the web keystore's signing RNG. That behavior is useful for repeatable tests, but it should not be available to a client that may submit live transactions.
I suggest keeping one Client::rng for every client operation and seeding it from the operating system in normal builds. Whole-client deterministic seeding can move to the testing feature or the mock client. Account recovery can keep its explicit account seed.
With that setup, I think this PR can remove the second RNG field and the public secure_rng() accessor. ClientRng::inner_mut() should also be limited to testing if production code has no need to replace the generator after construction.
That smaller implementation would keep the CryptoRng requirement and the ChaCha20Rng default. It would route the current secure_rng call sites through the one client RNG. The web SDK can then stop passing createClient(seed) into the production client builder while leaving newWallet(initSeed) unchanged.
Does this match the intended role of the client seed? If another production caller needs to inject its own CryptoRng, I may of course have missed something!
| } | ||
|
|
||
| /// Optionally provide a custom RNG. | ||
| /// Optionally provide a custom RNG for note serial numbers, script arguments and account |
There was a problem hiding this comment.
Requiring CryptoRng is a good step. Web account recovery already uses newWallet(initSeed), so could we keep recovery there and make this whole-client override test-only, unless there's another production use?
| /// Returns a reference to the client's secure random number generator. This can be used to | ||
| /// generate randomness for secret values such as account keys, and the nonces that seal | ||
| /// transaction inputs. | ||
| pub fn secure_rng(&mut self) -> &mut ClientRng { |
There was a problem hiding this comment.
If whole-client overrides are limited to tests, every production operation can use the same OS-seeded RNG (and we would not need to return a mutable variant of it in those production paths.
nit: the name implies security, but that's contextual. Could we remove secure_rng() and keep a single Client::rng() instead?
|
|
||
| ### Breaking Changes | ||
|
|
||
| * [BREAKING][removal][rust] Removed the `miden_client::crypto::RandomCoin` re-export. Use a `rand` CSPRNG such as `ChaCha20Rng`, plus the new `miden_client::crypto::draw_felt` / `draw_word` helpers where a `Felt` or `Word` is needed from a generator that does not implement `FeltRng` ([#2414](https://github.com/0xMiden/rust-sdk/pull/2414)). |
There was a problem hiding this comment.
The migration path here does not compile because both helpers live under miden_client::rng. Please change this to miden_client::rng::{draw_felt, draw_word} if the helpers remain public.
Closes #2204
RandomCoinwithChaCha20Rng.ClientBuilder::rngnow requires the RNG to implementCryptoRng(i.e.RandomCoinis no longer accepted, since it is not aCryptoRng).Client::secure_rng, a second RNG intended to be used to generate randomness for secret values.trybuildtest asserting thatClientBuilder::rngrejects aFeltRngwhich is not aCryptoRng.