stratum-mining / stratum

stratum
https://stratumprotocol.org
Other
219 stars 126 forks source link

Refactor: `noise-sv2` crate #1130

Open rrybarczyk opened 2 months ago

rrybarczyk commented 2 months ago

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

Shourya742 commented 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:

We should propagate these errors instead of using unwrap and allow the implementing binary to handle them appropriately.

Fi3 commented 2 months ago

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.

Shourya742 commented 2 months ago

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.

Shourya742 commented 2 months ago

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.

rrybarczyk commented 2 months ago

Considering the comment by @plebhash here: #916 (comment), 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.

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
Shourya742 commented 2 months ago

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.

plebhash commented 2 months ago

potentially relevant here: https://github.com/stratum-mining/sv2-spec/issues/65

Shourya742 commented 2 months ago

Reminder: Add a unit test to the noise-sv2 module. See discussion: https://github.com/stratum-mining/stratum/pull/1111#discussion_r1735036264

Shourya742 commented 2 months ago

remove redundant unused code in module: https://github.com/stratum-mining/stratum/pull/1111#discussion_r1733264185

rrybarczyk commented 1 month ago

The following may be unused imports in the handshake.rs test module:

rrybarczyk commented 1 month ago

Perhaps test.rs is a case where we should have a proper integration test using the tests/ directory.

rrybarczyk commented 1 month ago

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.

rrybarczyk commented 1 month ago

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)?

rrybarczyk commented 1 month ago

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>).

rrybarczyk commented 1 month ago

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.

rrybarczyk commented 1 month ago

Error variants that I cannot find uses of in the entire repo:

Fi3 commented 1 month 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`**
  ```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.

Fi3 commented 1 month ago

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.

why?

Fi3 commented 1 month ago

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

jbesraa commented 1 month ago

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.

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.

jbesraa commented 1 month 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`**
  ```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.

plebhash commented 1 month ago

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.

Fi3 commented 1 month 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`**
  ```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.

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.

rrybarczyk commented 1 month ago

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.

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.

rrybarczyk commented 1 month ago

Consistent Implementation and Naming that Adheres to the Noise Protocol Specification

Noise protocol reference link.

@Shourya742 may also have identified more instances that pertain to more protocol details.

Shourya742 commented 1 month ago

Consistent Implementation and Naming that Adheres to the Noise Protocol Specification

Noise protocol reference link.

  • We have 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.

@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 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.

Fi3 commented 1 month ago

Consistent Implementation and Naming that Adheres to the Noise Protocol Specification

Noise protocol reference link.

  • We have 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.

@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 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.

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?

Shourya742 commented 1 month ago

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

Fi3 commented 1 month ago

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

nack for me is working well and I don't think that the code lack clarity.

rrybarczyk commented 1 month ago

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 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.

plebhash commented 1 month ago

I think NoiseCodec is a bad name, because it implies encoding and decoding, while the actual idea is encrypting and decrypting.

https://github.com/stratum-mining/stratum/blob/ab0ddd625706698c47d44b9b4e4f985c39be18db/protocols/v2/noise-sv2/src/lib.rs#L22-L25


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>,
} 
plebhash commented 1 month ago

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 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:

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

plebhash commented 1 month ago

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 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>).

https://github.com/stratum-mining/stratum/issues/1130#issuecomment-2347092045

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.

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

Fi3 commented 1 month ago

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 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 for codec_sv2 (which operates on a higher level of abstraction)... and we already have something like this there, which is codec_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 of SymmetricState and HandshakeState into noise_sv2, and then this complexity can be abstracted away via codec_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:

  1. is easy to do mistakes
  2. this implementation have been extensively tested with unit tests and against other implementation
  3. this implementation have been benchmarked and it is pretty fast (I can't find anymore the benches, but it was significantly faster the the old one)
Fi3 commented 1 month ago

I think NoiseCodec is a bad name, because it implies encoding and decoding, while the actual idea is encrypting and decrypting.

https://github.com/stratum-mining/stratum/blob/ab0ddd625706698c47d44b9b4e4f985c39be18db/protocols/v2/noise-sv2/src/lib.rs#L22-L25

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>,
} 

for the reasons that I enumerated in my prev message I would be very careful here. Agree that NoiseCodec is bad name

plebhash commented 1 month ago

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

plebhash commented 1 month ago

aed_cipher.rs seems to be a typo, this file/module should be called aead_cipher.rs

Fi3 commented 1 month ago

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

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.

plebhash commented 1 month ago

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

Shourya742 commented 4 weeks ago

Change VERSION to CERTIFICATE_FORMAT_VERSION in Responder.rs. See #1111 (comment) for more context

plebhash commented 3 weeks ago

we should evaluate visibility of all elements of the crate

jbesraa commented 3 weeks ago

https://github.com/stratum-mining/stratum/pull/1111#discussion_r1791396410

Shourya742 commented 3 weeks ago

https://github.com/stratum-mining/stratum/pull/1111#discussion_r1799547146

jbesraa commented 3 weeks ago

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

rrybarczyk commented 2 weeks ago

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

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

GitGab19 commented 2 weeks ago

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

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

I would remove it in the refactoring PRs, for now we should take note of that in the specific issue

rrybarczyk commented 2 weeks ago

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

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

I would remove it in the refactoring PRs, for now we should take note of that in the specific issue

Agree.

jbesraa commented 2 weeks ago

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

rrybarczyk commented 2 weeks ago

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).

plebhash commented 1 week ago

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).

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