Open rrybarczyk opened 2 months ago
I noticed a few unwrap
calls in the initiator
, responder
, and signature
modules. It's generally not advisable to use unwrap
in a library crate since it can cause the program to panic if an error occurs. Below are the locations where unwrap
is being used:
initiator.rs
let plaintext: [u8; SIGNATURE_NOISE_MESSAGE_SIZE] = to_decrypt.try_into().unwrap();
let signature_message: SignatureNoiseMessage = plaintext.into();
let rs_pub_key = PublicKey::from_ellswift(elligatorswift_theirs_static)
.x_only_public_key()
.0
.serialize();
let rs_pk_xonly = XOnlyPublicKey::from_slice(&rs_pub_key).unwrap();
responder.rs
// 7. appends `EncryptAndHash(SIGNATURE_NOISE_MESSAGE)` to the buffer
let valid_from = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
signature_message.rs
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs() as u32;
let version = u16::from_le_bytes(value[0..2].try_into().unwrap());
let valid_from = u32::from_le_bytes(value[2..6].try_into().unwrap());
let not_valid_after = u32::from_le_bytes(value[6..10].try_into().unwrap());
let signature = value[10..74].try_into().unwrap();
We should propagate these errors instead of using unwrap
and allow the implementing binary to handle them appropriately.
they are inffalible, if you prefer you can use expect. I strongly suggest to not propagate error for impossible cases as we would only make the code harder to understand.
Based on the discussion about using the multi-cipher (referenced here: https://github.com/stratum-mining/stratum/discussions/916#discussioncomment-10416620), we need to remove AES_256_GCM from our codebase and update the specs accordingly.
Considering the comment by @plebhash here: https://github.com/stratum-mining/stratum/discussions/916#discussioncomment-9491609, and the removal of aes_256_gcm
, we will now use chacha20poly1305::Error
instead of aes_gcm::Error
. Although we could have used aead::Error
, since we've finalized using only chacha20poly1305
, it makes sense to use chacha20poly1305::Error
now.
Considering the comment by @plebhash here: #916 (comment), and the removal of
aes_256_gcm
, we will now usechacha20poly1305::Error
instead ofaes_gcm::Error
. Although we could have usedaead::Error
, since we've finalized using onlychacha20poly1305
, it makes sense to usechacha20poly1305::Error
now.
Just so we know, the aes-gcm
lib appears in the util/buffer/Cargo.toml
as well and should be removed.
%rg aes_gcm -i -l
protocols/v2/noise-sv2/src/cipher_state.rs
protocols/v2/noise-sv2/src/aed_cipher.rs
protocols/v2/noise-sv2/src/responder.rs
protocols/v2/noise-sv2/src/handshake.rs
protocols/v2/noise-sv2/src/lib.rs
protocols/v2/noise-sv2/src/initiator.rs
protocols/v2/noise-sv2/src/error.rs
protocols/v2/noise-sv2/tmp.rs
utils/buffer/src/lib.rs
utils/buffer/src/buffer.rs
utils/buffer/src/buffer_pool/mod.rs
Based on the discussion about using the multi-cipher (referenced here: #916 (comment)), we need to remove AES_256_GCM from our codebase and update the specs accordingly.
The specs have been updated with this PR.
potentially relevant here: https://github.com/stratum-mining/sv2-spec/issues/65
Reminder: Add a unit test to the noise-sv2 module. See discussion: https://github.com/stratum-mining/stratum/pull/1111#discussion_r1735036264
remove redundant unused code in module: https://github.com/stratum-mining/stratum/pull/1111#discussion_r1733264185
The following may be unused imports in the handshake.rs
test module:
secp256k1::ecdh::SharedSecret
secp256k1::ecdh::XOnlyPublicKey
Perhaps test.rs
is a case where we should have a proper integration test using the tests/
directory.
Reminder that all imports should be at the top of the file, meaning we should never be calling crate::<Type>
inside actual logic. Once case of this is calling crate::NoiseCodec
in the Initiator::step_2
method.
Because docs on private modules are not rendered by cargo docs by default (will render if the --document-private-items
flag is present when generating), we should really think about what documentation will be included or excluded. For example, the initiator
and responder
modules are private, but the Initiator
and Responder
structs are public. So the documentation at the top of these files are not accessible by default.
Perhaps we make these modules public? Or perhaps when we publish the final documentation, we publish the private logic docs as well (if this is an option)?
In error::Error
, what is the difference between the UnsupportedCiphers(Vec<u8>)
and theInvalidCipherChosed(Vec<u8>)
? If there is no difference, we should remove InvalidCipherChosed(Vec<u8>)
in support of UnsupportedCiphers(Vec<u8>)
.
Otherwise, if both are needed, we need to fix the grammatical error: InvalidCipherChosed(Vec<u8>)
-> InvalidCipherChosen(Vec<u8>)
.
In the error
module, we should not import use aes_gcm::Error as AesGcm;
. Instead we should define the variant as AesGcm(aes_gcm::Error)
. Also the impl From
will need to updated with this change.
Error variants that I cannot find uses of in the entire repo:
CipherListMustBeNonEmpty
UnsupportedCiphers
InvalidCipherList
InvalidCipherChosed
(see related comment)InvalidCipherState
I noticed a few
unwrap
calls in theinitiator
,responder
, andsignature
modules. It's generally not advisable to useunwrap
in a library crate since it can cause the program to panic if an error occurs. Below are the locations whereunwrap
is being used:* **`initiator.rs`** ```rust let plaintext: [u8; SIGNATURE_NOISE_MESSAGE_SIZE] = to_decrypt.try_into().unwrap(); let signature_message: SignatureNoiseMessage = plaintext.into(); let rs_pub_key = PublicKey::from_ellswift(elligatorswift_theirs_static) .x_only_public_key() .0 .serialize(); let rs_pk_xonly = XOnlyPublicKey::from_slice(&rs_pub_key).unwrap(); ``` * **`responder.rs`** ```rust // 7. appends `EncryptAndHash(SIGNATURE_NOISE_MESSAGE)` to the buffer let valid_from = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); ``` * **`signature_message.rs`** ```rust let now = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs() as u32; let version = u16::from_le_bytes(value[0..2].try_into().unwrap()); let valid_from = u32::from_le_bytes(value[2..6].try_into().unwrap()); let not_valid_after = u32::from_le_bytes(value[6..10].try_into().unwrap()); let signature = value[10..74].try_into().unwrap(); ```
We should propagate these errors instead of using
unwrap
and allow the implementing binary to handle them appropriately.
not agree if the code is infallibe unwrap or expect is a fare better solution that propoagate the error. We can put some assertion to be extrasafe.
Reminder that all imports should be at the top of the file, meaning we should never be calling
crate::<Type>
inside actual logic. Once case of this is callingcrate::NoiseCodec
in theInitiator::step_2
method.
why?
Error variants that I cannot find uses of in the entire repo:
* `CipherListMustBeNonEmpty` * `UnsupportedCiphers` * `InvalidCipherList` * `InvalidCipherChosed` (see related [comment](https://github.com/stratum-mining/stratum/issues/1130#issuecomment-2347084401)) * `InvalidCipherState`
if not used better to remove them, remember to bump minor version if you do it, otherwise we will get compilation error on importers
Reminder that all imports should be at the top of the file, meaning we should never be calling
crate::<Type>
inside actual logic. Once case of this is callingcrate::NoiseCodec
in theInitiator::step_2
method.
In general I agree with this approach but I think there are some exceptions. If you are using a module from tokio
that also exist in the standard library, for example tokio::time::sleep
and std::thread::sleep
, it would be better to write the full path where ever it is used to make it easier/quicker to understand where the module is imported from.
I noticed a few
unwrap
calls in theinitiator
,responder
, andsignature
modules. It's generally not advisable to useunwrap
in a library crate since it can cause the program to panic if an error occurs. Below are the locations whereunwrap
is being used:* **`initiator.rs`** ```rust let plaintext: [u8; SIGNATURE_NOISE_MESSAGE_SIZE] = to_decrypt.try_into().unwrap(); let signature_message: SignatureNoiseMessage = plaintext.into(); let rs_pub_key = PublicKey::from_ellswift(elligatorswift_theirs_static) .x_only_public_key() .0 .serialize(); let rs_pk_xonly = XOnlyPublicKey::from_slice(&rs_pub_key).unwrap();
responder.rs
// 7. appends `EncryptAndHash(SIGNATURE_NOISE_MESSAGE)` to the buffer let valid_from = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs();
signature_message.rs
let now = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs() as u32; let version = u16::from_le_bytes(value[0..2].try_into().unwrap()); let valid_from = u32::from_le_bytes(value[2..6].try_into().unwrap()); let not_valid_after = u32::from_le_bytes(value[6..10].try_into().unwrap()); let signature = value[10..74].try_into().unwrap();
We should propagate these errors instead of using
unwrap
and allow the implementing binary to handle them appropriately.not agree if the code is infallibe unwrap or expect is a fare better solution that propoagate the error. We can put some assertion to be extrasafe.
I think expect
is generally better than unwrap
because the bit of context it provides. Maybe we can also utilize https://doc.rust-lang.org/std/macro.debug_assert.html.
IMO though, it is best to add the error variants and keep the code consistent without panics.
not agree if the code is infallibe unwrap or expect is a fare better solution that propoagate the error.
if the code is provably safe (it could never panic under any circumstances), then it makes sense to use expect
with a message that makes it very clear that there will never be a panic there.
For example:
let valid_from = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
- .unwrap()
+ .expect("std::time::SystemTime::now() should always be later than std::time::UNIX_EPOCH")
.as_secs();
I'm against using unwrap
, because it doesn't make this point explicitly clear.
We can put some assertion to be extrasafe.
I don't think this makes sense. The only thing an assertion would do is to panic, which is exactly what would happen with the unwrap
, so it would be completely redundant.
overall, my strong stance on this discussion is:
we cannot ever have our libs doing panics for edge cases... a robust library has proper error handling
and if we're making exceptions for cases we are 100% sure there will never be a panic, we should make that explicitly clear.
I noticed a few
unwrap
calls in theinitiator
,responder
, andsignature
modules. It's generally not advisable to useunwrap
in a library crate since it can cause the program to panic if an error occurs. Below are the locations whereunwrap
is being used:* **`initiator.rs`** ```rust let plaintext: [u8; SIGNATURE_NOISE_MESSAGE_SIZE] = to_decrypt.try_into().unwrap(); let signature_message: SignatureNoiseMessage = plaintext.into(); let rs_pub_key = PublicKey::from_ellswift(elligatorswift_theirs_static) .x_only_public_key() .0 .serialize(); let rs_pk_xonly = XOnlyPublicKey::from_slice(&rs_pub_key).unwrap();
responder.rs
// 7. appends `EncryptAndHash(SIGNATURE_NOISE_MESSAGE)` to the buffer let valid_from = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs();
signature_message.rs
let now = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs() as u32; let version = u16::from_le_bytes(value[0..2].try_into().unwrap()); let valid_from = u32::from_le_bytes(value[2..6].try_into().unwrap()); let not_valid_after = u32::from_le_bytes(value[6..10].try_into().unwrap()); let signature = value[10..74].try_into().unwrap();
We should propagate these errors instead of using `unwrap` and allow the implementing binary to handle them appropriately.
not agree if the code is infallibe unwrap or expect is a fare better solution that propoagate the error. We can put some assertion to be extrasafe.
I think
expect
is generally better thanunwrap
because the bit of context it provides. Maybe we can also utilize https://doc.rust-lang.org/std/macro.debug_assert.html.IMO though, it is best to add the error variants and keep the code consistent without panics.
agree that using expect rather then unwrap is always better. Completely disagree with adding error for things that can not fail, otherwise we should do that anytime that we allocate (allocate can actually fail code above not) or when we index a vector. There are obvious cases where adding errors is only a price that do not make sense to pay.
Reminder that all imports should be at the top of the file, meaning we should never be calling
crate::<Type>
inside actual logic. Once case of this is callingcrate::NoiseCodec
in theInitiator::step_2
method.why?
Because when I open a module, I want to immediately see everything that is being imported at the top. I think it is more readable, compared to scrolling through the code and then all of a sudden seeing there are more data types being imported further down. I believe it is much cleaner with all imports listed immediately at the top.
Noise protocol reference link.
HandshakeOp
and TestHandShake
, we need to make sure we standardize on Handshake
with a lowercase "s".@Shourya742 may also have identified more instances that pertain to more protocol details.
Consistent Implementation and Naming that Adheres to the Noise Protocol Specification
Noise protocol reference link.
- We have
HandshakeOp
andTestHandShake
, we need to make sure we standardize onHandshake
with a lowercase "s".@Shourya742 may also have identified more instances that pertain to more protocol details.
@Fi3 , For any Noise protocol, we have three key objects for a handshake:
k
), nonce, and the AEAD algorithm (in our case, ChaCha20Poly1305).ck
), handshake hash (h
), and includes the cipher state.s
, rs
, e
, and re
(static and ephemeral key pairs).However, in our implementation, the Initiator
and Responder
structs are combined with the Handshake Object, and the SymmetricState Object is referred to as HandshakeOps
. Should we consider changing this to align more closely with the Noise protocol, using the correct names? This would make it less confusing for others reviewing our code alongside the Noise framework specification.
Consistent Implementation and Naming that Adheres to the Noise Protocol Specification
Noise protocol reference link.
- We have
HandshakeOp
andTestHandShake
, we need to make sure we standardize onHandshake
with a lowercase "s".@Shourya742 may also have identified more instances that pertain to more protocol details.
@Fi3 , For any Noise protocol, we have three key objects for a handshake:
1. **CipherState Object**: Responsible for defining the key (`k`), nonce, and the AEAD algorithm (in our case, ChaCha20Poly1305). 2. **SymmetricState Object**: Manages the chaining key (`ck`), handshake hash (`h`), and includes the cipher state. 3. **Handshake Object**: Contains the SymmetricState, along with `s`, `rs`, `e`, and `re` (static and ephemeral key pairs).
However, in our implementation, the
Initiator
andResponder
structs are combined with the Handshake Object, and the SymmetricState Object is referred to asHandshakeOps
. Should we consider changing this to align more closely with the Noise protocol, using the correct names? This would make it less confusing for others reviewing our code alongside the Noise framework specification.
Personally I find HandshakeOp
a better name for the trait that define the handshake operations. Which names do you want to change and with what?
I would personally prefer the implementation to align more closely with the Noise NX protocol. We already have the CipherState
, but I would also introduce a SymmetricState
object, removing the handshakeOps
. The SymmetricState
will handle key derivation and encryption for the handshake. I would also create a HandshakeState
object that contains the client and server keys along with the SymmetricState
. I plan to redefine the Initiator
and Responder
structs to incorporate the final cipher keys, allowing them to encode and decode messages after the handshake is completed. While the current implementation functions well, I think if we all agree, we can move forward with this change to bring it closer to Noise NX. However, we also have the option to stick with the current implementation.
cc: @Fi3 @rrybarczyk
I would personally prefer the implementation to align more closely with the Noise NX protocol. We already have the
CipherState
, but I would also introduce aSymmetricState
object, removing thehandshakeOps
. TheSymmetricState
will handle key derivation and encryption for the handshake. I would also create aHandshakeState
object that contains the client and server keys along with theSymmetricState
. I plan to redefine theInitiator
andResponder
structs to incorporate the final cipher keys, allowing them to encode and decode messages after the handshake is completed. While the current implementation functions well, I think if we all agree, we can move forward with this change to bring it closer to Noise NX. However, we also have the option to stick with the current implementation. cc: @Fi3 @rrybarczyk
nack for me is working well and I don't think that the code lack clarity.
I would personally prefer the implementation to align more closely with the Noise NX protocol. We already have the
CipherState
, but I would also introduce aSymmetricState
object, removing thehandshakeOps
. TheSymmetricState
will handle key derivation and encryption for the handshake. I would also create aHandshakeState
object that contains the client and server keys along with theSymmetricState
. I plan to redefine theInitiator
andResponder
structs to incorporate the final cipher keys, allowing them to encode and decode messages after the handshake is completed. While the current implementation functions well, I think if we all agree, we can move forward with this change to bring it closer to Noise NX. However, we also have the option to stick with the current implementation. cc: @Fi3 @rrybarczyk
I think it is worth while to identify the difference between the Noise protocol specification and our current implementation. We should adhere as close to the specification as possible as this is a very important crate.
@Shourya742 continue to identify the differences, then we can discuss these areas for potential refactor.
I think NoiseCodec
is a bad name, because it implies encoding and decoding, while the actual idea is encrypting and decrypting.
edit:
after we drop support for AES-GCM
cipher, we will be able to further simplify things because enum GenericCipher
will not be needed anymore.
So I would suggest something like this:
-pub struct NoiseCodec {
+pub struct NoiseEngine {
- encryptor: GenericCipher,
+ encryptor: Cipher<ChaCha20Poly1305>,
- decryptor: GenericCipher,
+ decryptor: Cipher<ChaCha20Poly1305>,
}
I would personally prefer the implementation to align more closely with the Noise NX protocol. We already have the
CipherState
, but I would also introduce aSymmetricState
object, removing thehandshakeOps
. TheSymmetricState
will handle key derivation and encryption for the handshake. I would also create aHandshakeState
object that contains the client and server keys along with theSymmetricState
. I plan to redefine theInitiator
andResponder
structs to incorporate the final cipher keys, allowing them to encode and decode messages after the handshake is completed. While the current implementation functions well, I think if we all agree, we can move forward with this change to bring it closer to Noise NX. However, we also have the option to stick with the current implementation. cc: @Fi3 @rrybarczykI think it is worth while to identify the difference between the Noise protocol specification and our current implementation. We should adhere as close to the specification as possible as this is a very important crate.
@Shourya742 continue to identify the differences, then we can discuss these areas for potential refactor.
based on my learnings around codec_sv2
+ framing_sv2
, I would also agree with @Shourya742 and @rrybarczyk
HandshakeOps
sounds like a convenience that would be better fit for codec_sv2
and framing_sv2
(which operate on a higher level of abstraction)... and we already have something like this there, for example:
codec_sv2::State::HandShake(HandshakeRole)
framing_sv2::framing::HandShakeFrame
for noise_sv2
, I would prefer if this crate follows the spec as closely as possible, which would mean the introduction of SymmetricState
and HandshakeState
into noise_sv2
then this complexity can be abstracted away via codec_sv2
and framing_sv2
replying to 3 comments by @rrybarczyk
https://github.com/stratum-mining/stratum/issues/1130#issuecomment-2347168122
Error variants that I cannot find uses of in the entire repo:
CipherListMustBeNonEmpty
UnsupportedCiphers
InvalidCipherList
InvalidCipherChosed
(see related comment)InvalidCipherState
https://github.com/stratum-mining/stratum/issues/1130#issuecomment-2347084401
In
error::Error
, what is the difference between theUnsupportedCiphers(Vec<u8>)
and theInvalidCipherChosed(Vec<u8>)
? If there is no difference, we should removeInvalidCipherChosed(Vec<u8>)
in support ofUnsupportedCiphers(Vec<u8>)
.Otherwise, if both are needed, we need to fix the grammatical error:
InvalidCipherChosed(Vec<u8>)
->InvalidCipherChosen(Vec<u8>)
.
https://github.com/stratum-mining/stratum/issues/1130#issuecomment-2347092045
In the
error
module, we should not importuse aes_gcm::Error as AesGcm;
. Instead we should define the variant asAesGcm(aes_gcm::Error)
. Also theimpl From
will need to updated with this change.
if we remember we will drop support for AES-GCM
cipher, all these errors will be greatly simplified as a result of only one cipher being supported
I would personally prefer the implementation to align more closely with the Noise NX protocol. We already have the
CipherState
, but I would also introduce aSymmetricState
object, removing thehandshakeOps
. TheSymmetricState
will handle key derivation and encryption for the handshake. I would also create aHandshakeState
object that contains the client and server keys along with theSymmetricState
. I plan to redefine theInitiator
andResponder
structs to incorporate the final cipher keys, allowing them to encode and decode messages after the handshake is completed. While the current implementation functions well, I think if we all agree, we can move forward with this change to bring it closer to Noise NX. However, we also have the option to stick with the current implementation. cc: @Fi3 @rrybarczykI think it is worth while to identify the difference between the Noise protocol specification and our current implementation. We should adhere as close to the specification as possible as this is a very important crate. @Shourya742 continue to identify the differences, then we can discuss these areas for potential refactor.
based on my learnings around
codec_sv2
while I review #1040, I would also agree with @Shourya742 and @rrybarczyk
HandshakeOps
sounds like a convenience that would be better fit forcodec_sv2
(which operates on a higher level of abstraction)... and we already have something like this there, which iscodec_sv2::State::HandShake(HandshakeRole)
for
noise_sv2
, I would prefer if this crate follows the spec as closely as possible, which would mean the introduction ofSymmetricState
andHandshakeState
intonoise_sv2
, and then this complexity can be abstracted away viacodec_sv2::State::HandShake(HandshakeRole)
Handshake is part of Noise. The crate already "follow" the spec as close as possible since it implement them. HandshakeOp and CipherState are traits if you just want to change the trait name is ok with me. But before refactoring noise keep in mind that:
I think
NoiseCodec
is a bad name, because it implies encoding and decoding, while the actual idea is encrypting and decrypting.edit:
after we drop support for
AES-GCM
cipher, we will be able to further simplify things becauseenum GenericCipher
will not be needed anymore.So I would suggest something like this:
-pub struct NoiseCodec { +pub struct NoiseEngine { - encryptor: GenericCipher, + encryptor: Cipher<ChaCha20Poly1305>, - decryptor: GenericCipher, + decryptor: Cipher<ChaCha20Poly1305>, }
for the reasons that I enumerated in my prev message I would be very careful here. Agree that NoiseCodec is bad name
the AeadCipher
trait is currently defined under a private module, which means only code inside noise_sv2
crate is able to implement it
and it seems it only exists under the assumption that more than one single cipher is supported
but once AES-GCM
support is dropped, we will only have one single struct (ChaCha20Poly1305
) implementing the AeadCipher
trait
so we should probably eliminate the AeadCipher
trait
if we choose to keep the AeadCipher
trait after we drop AES-GCM
, we should probably make the aed_cipher
module public... this way, a consumer of noise_sv2
crate could choose to implement their own cipher
however I'm not sure how realistic this use-case is
aed_cipher.rs
seems to be a typo, this file/module should be called aead_cipher.rs
the
AeadCipher
trait is currently defined under a private module, which means only code insidenoise_sv2
crate is able to implement itand it seems it only exists under the assumption that more than one single cipher is supported
but once
AES-GCM
support is dropped, we will only have one single struct (ChaCha20Poly1305
) implementing theAeadCipher
traitso we should probably eliminate the
AeadCipher
traitif we choose to keep the
AeadCipher
trait after we dropAES-GCM
, we should probably make theaed_cipher
module public... this way, a consumer ofnoise_sv2
crate could choose to implement their own cipherhowever I'm not sure how realistic this use-case is
maybe a future version of sv2? I'm not super happy to change code in this crate since is very hard to debug (and it works and it is fast), also leave it like it is is not really bad, probably would be better without the trait, but we still have a clean interface with the trait.
this comment will probably be erased by #1111 but it is an indication that this function should probably be private, not public https://github.com/stratum-mining/stratum/blob/060131edeae2400e77476763d06809c73e86b2d1/protocols/v2/noise-sv2/src/cipher_state.rs#L196-L197
see https://github.com/stratum-mining/stratum/discussions/916#discussioncomment-10756423 for more context
Change VERSION
to CERTIFICATE_FORMAT_VERSION
in Responder.rs. See #1111 (comment) for more context
we should evaluate visibility of all elements of the crate
Interestingly, there is a src/test.rs
file in the crate(https://github.com/stratum-mining/stratum/blob/main/protocols/v2/noise-sv2/src/test.rs). We should move the test to lib.rs
and remove the extra file
Interestingly, there is a
src/test.rs
file in the crate(https://github.com/stratum-mining/stratum/blob/main/protocols/v2/noise-sv2/src/test.rs). We should move the test tolib.rs
and remove the extra file
I posed a question somewhere in this PR's conversation suggesting we remove test.rs
completely as we have the examples now. We just need to consider: do we want to remove it in this PR, or in the technical debt issue?
cc: @plebhash, @GitGab19
Interestingly, there is a
src/test.rs
file in the crate(https://github.com/stratum-mining/stratum/blob/main/protocols/v2/noise-sv2/src/test.rs). We should move the test tolib.rs
and remove the extra fileI posed a question somewhere in this PR's conversation suggesting we remove
test.rs
completely as we have the examples now. We just need to consider: do we want to remove it in this PR, or in the technical debt issue?cc: @plebhash, @GitGab19
I would remove it in the refactoring PRs, for now we should take note of that in the specific issue
Interestingly, there is a
src/test.rs
file in the crate(https://github.com/stratum-mining/stratum/blob/main/protocols/v2/noise-sv2/src/test.rs). We should move the test tolib.rs
and remove the extra fileI posed a question somewhere in this PR's conversation suggesting we remove
test.rs
completely as we have the examples now. We just need to consider: do we want to remove it in this PR, or in the technical debt issue? cc: @plebhash, @GitGab19I would remove it in the refactoring PRs, for now we should take note of that in the specific issue
Agree.
Why remove it entirely and not having tests in lib.rs
? Examples should provide a direction for library users on how to use it, while tests should guarantee the library is correctly implemented
I think we should consider implementing noise_sv2
in a way that does not require std
, such that it can be used on various OSs (like for firmware).
I think we should consider implementing
noise_sv2
in a way that does not requirestd
, such that it can be used on various OSs (like for firmware).
that is a very good catch!
adding some extra context that will be relevant when we tackle this:
most protocols
crates already have support for no_std
(although we should probably make a general assessment to check if there's any other crate that also requires this change)
for the crates that already support no_std
, it originally was mandatory (meaning that every build would force no_std
)
but then we noticed that was becoming a blocker for https://github.com/stratum-mining/stratum/pull/985#issuecomment-2234328927 so we made no_std
into something to be opt-in (as a no_std
cargo feature flag) via #932
now we have #1230 that is proposing to invert this logic, making the opt-in feature flag to be std
Background
This task is an outcome of the
protocols
Rust docs issues tracked in #845.While documenting
protocols::v2::noise-sv2
in #1013, areas of potential code debt were identified. This issue servers as a place to list out these items to then be addressed in an organized manner. The initial Rust documentation effort was an immediate action, while a refactoring (which implies breaking API changes) is not so urgent priority, so for now we should leave this in the backlog for an appropriate moment in the future.Identified Potential Code Debt
noise_sv2::cipher_state::GenericCipher
enum + associated logic to its ownnoise_sv2::generic_cipher
module. Or, perhaps given the comment in the #916 discussion and the removal of AES256GCM in this sv2-spec PR, we do not need theGenericCipher
at all? Do we plan so support anything other thanChaCha20Poly1305
in the future?noise_sv2::cipher_state::Cipher
struct and associated logic into its ownnoise_sv2::cipher
module.unwraps
in theimpl From<[u8; 74]> for SignatureNoiseMessage
from
method.Result
type alias around our customError
enum. Should add and use this everywhere we have astd::result::Result
type.handshake::HandshakeOp
trait public so users can callResponder::generate_key()
.