-
Notifications
You must be signed in to change notification settings - Fork 11
Housekeeping #218
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
base: main
Are you sure you want to change the base?
Housekeeping #218
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR migrates the codebase from a custom SecretBox implementation to using the standard secrecy crate. The change also updates several dependencies including PyO3 to version 0.27, replaces serde_bytes with serde-encoded-bytes, and updates wasm-bindgen-derive to 0.3.
Key Changes:
- Replaced custom
SecretBox<T>implementation withsecrecy::SecretBox<T>, changing the API fromas_secret()/as_mut_secret()toexpose_secret()/expose_secret_mut() - Updated
SecretBoxto work with unsized types (SecretBox<[u8]>instead ofSecretBox<Vec<u8>>) - Updated PyO3 bindings to use new API (
Python::attachinstead ofPython::with_gil,PyStringinstead ofPyUnicode,Bound<'_, PyModule>) - Migrated from
serde_bytestoserde-encoded-bytesfor hex serialization - Moved helper functions
try_from_js_arrayandinto_js_arrayfrom local implementation towasm-bindgen-derivecrate
Reviewed Changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| ferveo-tdec/src/secret_box.rs | Deleted custom SecretBox implementation |
| ferveo-tdec/src/lib.rs | Removed secret_box module export, added secrecy import |
| ferveo-tdec/src/ciphertext.rs | Updated to use secrecy::SecretBox with expose_secret/expose_secret_mut methods |
| ferveo-tdec/src/api.rs | Changed encrypt signature to accept SecretBox<[u8]>, removed SecretBox from exports |
| ferveo-tdec/Cargo.toml | Added secrecy dependency, replaced serde_bytes with serde-encoded-bytes |
| ferveo/src/lib.rs | Moved SecretBox import to secrecy crate, updated MSG.to_vec() to MSG.into() |
| ferveo/src/api.rs | Updated encrypt signature and removed SecretBox export |
| ferveo/src/bindings_wasm.rs | Removed local try_from_js_array/into_js_array helpers, imported from wasm-bindgen-derive |
| ferveo/src/bindings_python.rs | Updated PyO3 API calls for 0.27 compatibility |
| ferveo/src/refresh.rs | Commented out broken test assertions and prefixed unused variables |
| ferveo/Cargo.toml | Added secrecy dependency |
| ferveo-wasm/tests/node.rs | Added into_js_array import from wasm-bindgen-derive |
| ferveo-wasm/Cargo.toml | Added wasm-bindgen and wasm-bindgen-derive dependencies |
| ferveo-python/src/lib.rs | Updated to use Bound<'_, PyModule> parameter |
| ferveo-python/ferveo/init.pyi | Changed init to new in type stubs |
| ferveo-python/Cargo.toml | Removed extension-module feature configuration |
| ferveo-common/src/serialization.rs | Migrated from serde_with::Bytes to serde-encoded-bytes SliceLike |
| ferveo-common/Cargo.toml | Added serde-encoded-bytes dependency |
| Cargo.toml | Updated workspace dependencies (pyo3 to 0.27, wasm-bindgen-derive to 0.3, added secrecy and serde-encoded-bytes) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ) -> JsResult<Vec<(api::Validator, api::Transcript)>> { | ||
| let messages = try_from_js_array::<ValidatorMessage>(messages)?; | ||
| let messages = | ||
| try_from_js_array::<ValidatorMessage>(messages).map_err(map_js_err)?; |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try_from_js_array function is now imported from wasm-bindgen-derive and its error handling has changed. The function now returns a Result that needs to be mapped with map_err(map_js_err). However, checking the usage pattern across the file, this error mapping is inconsistent with the removal of the old local implementation. The old implementation already had fmt::Display constraint that worked with map_js_err, but the new version from the derive crate may have a different error type. Verify that the error type from wasm-bindgen-derive::try_from_js_array implements fmt::Display and is compatible with map_js_err.
| try_from_js_array::<ValidatorMessage>(messages).map_err(map_js_err)?; | |
| try_from_js_array::<ValidatorMessage>(messages).map_err(|e| map_js_err(e.to_string()))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strange take from the copilot. map_js_err has a Display bound on its argument, if it compiles, it's going to work.
| ) -> Result<ChaCha20Poly1305> { | ||
| let mut prf_key = SecretBox::new(Vec::new()); | ||
| let mut prf_key = SecretBox::new( | ||
| vec![0u8; shared_secret.0.compressed_size()].into_boxed_slice(), |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a zero-initialized vector and then converting it to a boxed slice is inefficient. Consider using vec![0u8; shared_secret.0.compressed_size()].into_boxed_slice() or better yet, directly creating a boxed slice with Box::new([0u8; N]) if the size is known at compile time, or using Box::<[u8]>::new_zeroed_slice(n).assume_init() for runtime-known sizes.
| vec![0u8; shared_secret.0.compressed_size()].into_boxed_slice(), | |
| // SAFETY: new_zeroed_slice returns a Box<[u8]> where all bytes are zeroed. | |
| unsafe { Box::<[u8]>::new_zeroed_slice(shared_secret.0.compressed_size()).assume_init() }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure using unsafe is better than creating a vector. I don't think there's a way to get a dynamically allocated box with a given size directly, is there?
| // ) | ||
| // .unwrap(); | ||
| assert_ne!(original_private_key_share, original_private_key_share); | ||
| // assert_ne!(original_private_key_share, original_private_key_share); |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commented-out assertion assert_ne!(original_private_key_share, original_private_key_share) would always fail since it compares a value to itself. This indicates the test logic is incomplete or incorrect. Either remove this assertion entirely or fix it to compare the correct values (e.g., comparing the original share with a refreshed share).
| // assert_ne!(original_private_key_share, original_private_key_share); | |
| // assert_ne!(incorrect_private_key_share, original_private_key_share); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ @cygnusv ... huh?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a skipped test, so this isn't executed anyway. I commented the assertion because it was triggering a clippy warning (naturally). Not sure what's going on there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok. I missed that it was skipped.
| // ) | ||
| // .unwrap(); | ||
| assert_ne!(shared_private_key, shared_private_key); | ||
| // assert_ne!(shared_private_key, shared_private_key); |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commented-out assertion assert_ne!(shared_private_key, shared_private_key) would always fail since it compares a value to itself. This indicates the test logic is incomplete or incorrect. Either remove this assertion entirely or fix it to compare the correct values (e.g., comparing the original key with a refreshed key).
|
|
||
| // V | ||
| #[serde(with = "serde_bytes")] | ||
| #[serde(with = "SliceLike::<Hex>")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this specifically serializing as hex instead of bytes? Backwards compatibility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's serializing as hex in human-readable formats, and as bytes in binary formats. Same as in umbral. The binary format ABI won't change, unless serde_bytes was saving constant-sized byte arrays as serialize_tuple() in serde, which leads to inefficient serialization. I suppose I need to add vector tests here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Some vector tests would be good for reinforcement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a big serialization vector test in ferveo, before the serde-encoded-bytes commit.
| // ) | ||
| // .unwrap(); | ||
| assert_ne!(original_private_key_share, original_private_key_share); | ||
| // assert_ne!(original_private_key_share, original_private_key_share); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ @cygnusv ... huh?
|
This is RFR |
Type of PR:
Required reviews:
What this does:
pyo3to 0.27serde-encoded-bytescrate instead ofserde_bytesandserde_with::Bytes(can revert this if you're not interested in human-readable serialization; also note that for human-readable formats everything will currently be serialized as hex strings)wasm-bindgen-deriveto 0.3secrecy::SecretBoxNote that I had some linker problems both for Python and JS bindings, which seem to have been fixed by the bump of Pyo3 and the explicit
wasm-bindgenandjs-sysdependencies inferveo-wasm. Curious to see how CI will fare.For reviewers:
The serialization vector tests are checking the classes exported via Python bindings (specifically, via
ToBytes/FromBytestraits, which is what Python bindings use). There's a bunch of other serialization stuff that seems to be unused (e.g.ferveo_common::PublicKey::to_bytes/from_bytes) but I didn't touch it in this PR.