diff --git a/Cargo.toml b/Cargo.toml index 1c9fcaa61..78934f41f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ resolver = "2" # so that our dev-dependency features don't leak into products version = "0.86.14" authors = ["Signal Messenger LLC"] license = "AGPL-3.0-only" -rust-version = "1.85" +rust-version = "1.88" [workspace.lints.clippy] # Prefer TryFrom between integers unless truncation is desired. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6282ceb91..8fca72135 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,5 @@ v0.86.14 - TypeScript: Fix accidentally-lax typing for the non-deprecated overload of `Net.setRemoteConfig`. +- Upgrade MSRV to 1.88 + diff --git a/rust/attest/Cargo.toml b/rust/attest/Cargo.toml index 43c589b92..e368575ac 100644 --- a/rust/attest/Cargo.toml +++ b/rust/attest/Cargo.toml @@ -8,7 +8,7 @@ name = "attest" version = "0.1.0" authors.workspace = true license.workspace = true -rust-version = "1.85" +rust-version = "1.88" edition = "2024" [lints] diff --git a/rust/attest/src/dcap.rs b/rust/attest/src/dcap.rs index ec4592e6f..10fa134c9 100644 --- a/rust/attest/src/dcap.rs +++ b/rust/attest/src/dcap.rs @@ -93,16 +93,15 @@ pub fn verify_remote_attestation( let attestation = attest(evidence_bytes, endorsement_bytes, current_time)?; // 4. Verify the status of the IntelĀ® SGX TCB described in the chain. - if let TcbStanding::SWHardeningNeeded { advisory_ids } = attestation.tcb_standing { - if advisory_ids + if let TcbStanding::SWHardeningNeeded { advisory_ids } = attestation.tcb_standing + && advisory_ids .iter() .any(|id| !acceptable_sw_advisories.contains(&id.as_str())) - { - return Err(Error::new(format!( - "TCB contains unmitigated unaccepted advisory ids: {advisory_ids:?}" - )) - .into()); - } + { + return Err(Error::new(format!( + "TCB contains unmitigated unaccepted advisory ids: {advisory_ids:?}" + )) + .into()); } // 5. Verify the enclave measurements in the Quote reflect an enclave identity expected. diff --git a/rust/attest/src/dcap/endorsements.rs b/rust/attest/src/dcap/endorsements.rs index 3ceb0c030..c03f1ee57 100644 --- a/rust/attest/src/dcap/endorsements.rs +++ b/rust/attest/src/dcap/endorsements.rs @@ -106,10 +106,12 @@ impl TryFrom<&[u8]> for SgxEndorsements { let (offsets, data) = src.split_at(offsets_required_size); - // TODO: Use as_chunks instead at MSRV 1.88. + let (offsets, offsets_remainder) = offsets.as_chunks::<{ std::mem::size_of::() }>(); + // offsets_required_size is a multiple of std::mem::size_of:: + assert!(offsets_remainder.is_empty()); let offsets = offsets - .chunks_exact(4) - .map(|d| u32::from_le_bytes(d.try_into().expect("correct size")) as usize) + .iter() + .map(|d| u32::from_le_bytes(*d) as usize) .collect::>(); validate_offsets(&offsets, data)?; diff --git a/rust/bridge/shared/src/incremental_mac.rs b/rust/bridge/shared/src/incremental_mac.rs index ff5139162..a114d40fc 100644 --- a/rust/bridge/shared/src/incremental_mac.rs +++ b/rust/bridge/shared/src/incremental_mac.rs @@ -72,14 +72,11 @@ pub fn ValidatingMac_Initialize( } let incremental = Incremental::new(hmac, chunk_size as usize); const MAC_SIZE: usize = ::OutputSize::USIZE; - // TODO: When we reach an MSRV of 1.88, we can use as_chunks instead. - let macs = digests.chunks_exact(MAC_SIZE); - if !macs.remainder().is_empty() { + let (macs, macs_remainder) = digests.as_chunks::(); + if !macs_remainder.is_empty() { return None; } - Some(ValidatingMac(Some(incremental.validating(macs.map( - |chunk| <&[u8; MAC_SIZE]>::try_from(chunk).expect("split into correct size already"), - ))))) + Some(ValidatingMac(Some(incremental.validating(macs.iter())))) } #[bridge_fn] diff --git a/rust/bridge/shared/src/zkgroup.rs b/rust/bridge/shared/src/zkgroup.rs index 0b61bc583..76699808c 100644 --- a/rust/bridge/shared/src/zkgroup.rs +++ b/rust/bridge/shared/src/zkgroup.rs @@ -1073,7 +1073,11 @@ fn GroupSendEndorsementsResponse_IssueDeterministic( key_pair: &[u8], randomness: &[u8; RANDOMNESS_LEN], ) -> Vec { - assert!(concatenated_group_member_ciphertexts.len() % UUID_CIPHERTEXT_LEN == 0); + assert!( + concatenated_group_member_ciphertexts + .len() + .is_multiple_of(UUID_CIPHERTEXT_LEN) + ); let user_id_ciphertexts = concatenated_group_member_ciphertexts .chunks_exact(UUID_CIPHERTEXT_LEN) .map(|serialized| { @@ -1142,7 +1146,11 @@ fn GroupSendEndorsementsResponse_ReceiveAndCombineWithCiphertexts( let response = zkgroup::deserialize::(response_bytes) .expect("should have been parsed previously"); - assert!(concatenated_group_member_ciphertexts.len() % UUID_CIPHERTEXT_LEN == 0); + assert!( + concatenated_group_member_ciphertexts + .len() + .is_multiple_of(UUID_CIPHERTEXT_LEN) + ); let local_user_index = concatenated_group_member_ciphertexts .chunks_exact(UUID_CIPHERTEXT_LEN) .position(|serialized| serialized == local_user_ciphertext) diff --git a/rust/bridge/shared/types/src/ffi/convert.rs b/rust/bridge/shared/types/src/ffi/convert.rs index e94b659ea..2dc4beaa7 100644 --- a/rust/bridge/shared/types/src/ffi/convert.rs +++ b/rust/bridge/shared/types/src/ffi/convert.rs @@ -1063,21 +1063,15 @@ impl ResultTypeInfo for (A, B) { } impl ResultTypeInfo for Option<(A, B)> -// We can simplify this when our MSRV is 1.88, when pointers become Default. -// Meanwhile, we'll rely on the fact that every C type is zeroable. where - A::ResultType: zerocopy::FromZeros, - B::ResultType: zerocopy::FromZeros, + A::ResultType: Default, + B::ResultType: Default, { type ResultType = OptionalPairOf; fn convert_into(self) -> SignalFfiResult { let Some(value) = self else { - return Ok(OptionalPairOf { - present: false, - first: zerocopy::FromZeros::new_zeroed(), - second: zerocopy::FromZeros::new_zeroed(), - }); + return Ok(OptionalPairOf::default()); }; Ok(OptionalPairOf { present: true, diff --git a/rust/bridge/shared/types/src/hsm_enclave.rs b/rust/bridge/shared/types/src/hsm_enclave.rs index 2e514ba8f..36bfda578 100644 --- a/rust/bridge/shared/types/src/hsm_enclave.rs +++ b/rust/bridge/shared/types/src/hsm_enclave.rs @@ -27,7 +27,9 @@ impl HsmEnclaveClient { return Err(hsm_enclave::Error::InvalidPublicKeyError); } if trusted_code_hashes.is_empty() - || trusted_code_hashes.len() % hsm_enclave::CODE_HASH_SIZE != 0 + || !trusted_code_hashes + .len() + .is_multiple_of(hsm_enclave::CODE_HASH_SIZE) { return Err(hsm_enclave::Error::InvalidCodeHashError); } diff --git a/rust/bridge/shared/types/src/support/sequences.rs b/rust/bridge/shared/types/src/support/sequences.rs index acdb613f8..9121217f2 100644 --- a/rust/bridge/shared/types/src/support/sequences.rs +++ b/rust/bridge/shared/types/src/support/sequences.rs @@ -9,7 +9,6 @@ use std::sync::Arc; use libsignal_protocol::{ServiceId, ServiceIdFixedWidthBinaryBytes}; use rayon::iter::ParallelIterator as _; -use rayon::slice::ParallelSlice as _; use crate::*; @@ -39,11 +38,8 @@ impl<'a> ServiceIdSequence<'a> { Self(input) } - fn parse_single_chunk(chunk: &[u8]) -> ServiceId { - ServiceId::parse_from_service_id_fixed_width_binary( - chunk.try_into().expect("correctly split"), - ) - .expect(concat!( + fn parse_single_chunk(chunk: &ServiceIdFixedWidthBinaryBytes) -> ServiceId { + ServiceId::parse_from_service_id_fixed_width_binary(chunk).expect(concat!( "input should be a concatenated list of Service-Id-FixedWidthBinary, ", "but one ServiceId was invalid" )) @@ -51,25 +47,29 @@ impl<'a> ServiceIdSequence<'a> { } impl<'a> IntoIterator for ServiceIdSequence<'a> { - type IntoIter = std::iter::Map, fn(&[u8]) -> ServiceId>; + type IntoIter = std::iter::Map< + std::slice::Iter<'a, [u8; 17]>, + for<'b> fn(&'b ServiceIdFixedWidthBinaryBytes) -> ServiceId, + >; type Item = ServiceId; fn into_iter(self) -> Self::IntoIter { - // TODO: Use as_chunks when we reach MSRV 1.88. - self.0 - .chunks_exact(Self::SERVICE_ID_FIXED_WIDTH_BINARY_LEN) - .map(Self::parse_single_chunk) + self.0.as_chunks().0.iter().map(Self::parse_single_chunk) } } impl<'a> rayon::iter::IntoParallelIterator for ServiceIdSequence<'a> { - type Iter = rayon::iter::Map, fn(&[u8]) -> ServiceId>; + type Iter = rayon::iter::Map< + rayon::slice::Iter<'a, ServiceIdFixedWidthBinaryBytes>, + for<'b> fn(&'b ServiceIdFixedWidthBinaryBytes) -> ServiceId, + >; type Item = ServiceId; fn into_par_iter(self) -> Self::Iter { - // TODO: Use as_chunks when we reach MSRV 1.88. self.0 - .par_chunks_exact(Self::SERVICE_ID_FIXED_WIDTH_BINARY_LEN) + .as_chunks() + .0 + .into_par_iter() .map(Self::parse_single_chunk) } } diff --git a/rust/net/Cargo.toml b/rust/net/Cargo.toml index 694676eeb..1ee832f2e 100644 --- a/rust/net/Cargo.toml +++ b/rust/net/Cargo.toml @@ -2,7 +2,7 @@ name = "libsignal-net" version = "0.1.0" edition = "2024" -rust-version = "1.85" +rust-version = "1.88" authors.workspace = true license.workspace = true diff --git a/rust/net/infra/Cargo.toml b/rust/net/infra/Cargo.toml index 64cc96932..10a98fa63 100644 --- a/rust/net/infra/Cargo.toml +++ b/rust/net/infra/Cargo.toml @@ -2,7 +2,7 @@ name = "libsignal-net-infra" version = "0.1.0" edition = "2024" -rust-version = "1.85" +rust-version = "1.88" authors.workspace = true license.workspace = true diff --git a/rust/net/infra/src/errors.rs b/rust/net/infra/src/errors.rs index 6dd620d65..4a38edb51 100644 --- a/rust/net/infra/src/errors.rs +++ b/rust/net/infra/src/errors.rs @@ -104,12 +104,11 @@ impl From> for FailedHandshakeReason { // If we specifically have an *SSL* error, check if it's an *X509* error underneath. // (But not X509VerifyError::INVALID_CALL, which means we're not in the right state to // query for verification errors.) - if code == boring_signal::ssl::ErrorCode::SSL { - if let Some(cert_error_code) = value.ssl().and_then(|ssl| ssl.verify_result().err()) { - if cert_error_code != boring_signal::x509::X509VerifyError::INVALID_CALL { - return Self::Cert(cert_error_code); - } - } + if code == boring_signal::ssl::ErrorCode::SSL + && let Some(cert_error_code) = value.ssl().and_then(|ssl| ssl.verify_result().err()) + && cert_error_code != boring_signal::x509::X509VerifyError::INVALID_CALL + { + return Self::Cert(cert_error_code); } Self::OtherBoring(code) diff --git a/rust/net/infra/src/route.rs b/rust/net/infra/src/route.rs index 85319f82c..cd8a5e772 100644 --- a/rust/net/infra/src/route.rs +++ b/rust/net/infra/src/route.rs @@ -143,30 +143,10 @@ pub trait RouteProvider { /// The routes must be produced in the order in which connection attempts /// should be made. The iterator is allowed to borrow from `self` as an /// optimization. - /// - /// Why is `context` a `&` instead of a `&mut`? Because as of Jan 2025, - /// there's no way to prevent the lifetime in the type of `context` from - /// being captured in the opaque return type. That's important because there - /// are some implementations of this trait where it's necessary to combine - /// the output of two different comprising providers. If `context` was a - /// `&mut` the first call's exclusive borrow for its entire lifetime would - /// prevent the second call from being able to use the same `context`. - /// - /// There are two potential ways we could work around this: - /// - /// 1. Use the new precise-capture syntax introduced in Rust 1.82, and - /// stabilized for use in traits in Rust 1.87. - /// - /// 2. Introduce a named associated type that only captures `'s`, not `'c`. - /// This works now, but would require all returned iterator types to be - /// named. That would prevent us from using `Iterator::map` and other - /// combinators, or require any uses be `Box`ed and those tradeoffs - /// aren't (currently) worth the imprecision. - // TODO: when our MSRV >= 1.87, use precise captures and make context &mut. - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's; + context: &mut C, + ) -> impl Iterator + use<'s, C, Self>; } /// Context parameter passed to [`RouteProvider::routes`]. @@ -175,7 +155,7 @@ pub trait RouteProvider { /// implementer can use to make decisions about what routes to emit. pub trait RouteProviderContext { /// Returns a uniformly random [`usize`]. - fn random_usize(&self) -> usize; + fn random_usize(&mut self) -> usize; } /// A hostname in a route that can later be resolved to IP addresses. @@ -586,13 +566,13 @@ fn pull_next_route_delay(connects_in_progress: &FuturesUnordered) -> Durat PER_CONNECTION_WAIT_DURATION * connections_factor } -impl RouteProvider for &R { +impl<'a, R: RouteProvider> RouteProvider for &'a R { type Route = R::Route; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, 'a, C, R> { R::routes(self, context) } } @@ -646,10 +626,10 @@ pub mod testutils { impl RouteProvider for Vec { type Route = R; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - _context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + _context: &mut C, + ) -> impl Iterator + use<'s, R, C> { self.iter().cloned() } } @@ -673,7 +653,7 @@ pub mod testutils { } impl RouteProviderContext for FakeContext { - fn random_usize(&self) -> usize { + fn random_usize(&mut self) -> usize { UniformUsize::sample_single_inclusive(0, usize::MAX, &mut self.rng.borrow_mut()) .expect("non-empty range") } @@ -775,7 +755,7 @@ mod test { }, }; - let routes = RouteProvider::routes(&provider, &FakeContext::new()).collect_vec(); + let routes = RouteProvider::routes(&provider, &mut FakeContext::new()).collect_vec(); let expected_routes = vec![ WebSocketRoute { @@ -896,7 +876,7 @@ mod test { inner: direct_provider, }; - let routes = provider.routes(&FakeContext::new()).collect_vec(); + let routes = provider.routes(&mut FakeContext::new()).collect_vec(); assert_eq!( routes, @@ -958,7 +938,7 @@ mod test { inner: direct_provider, }; - let routes = provider.routes(&FakeContext::new()).collect_vec(); + let routes = provider.routes(&mut FakeContext::new()).collect_vec(); let expected_routes = vec![ TlsRoute { diff --git a/rust/net/infra/src/route/http.rs b/rust/net/infra/src/route/http.rs index 89b58921b..148ad555d 100644 --- a/rust/net/infra/src/route/http.rs +++ b/rust/net/infra/src/route/http.rs @@ -113,10 +113,10 @@ impl DomainFrontRouteProvider { impl RouteProvider for DomainFrontRouteProvider { type Route = HttpsTlsRoute>>; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C> { let Self { fronts, http_version, @@ -174,10 +174,10 @@ where F: RouteProvider>, { type Route = HttpsTlsRoute; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C, F, P> { let Self { direct_host_header, direct_http_version, @@ -274,7 +274,7 @@ mod test { }, }; - let routes = provider.routes(&FakeContext::new()).collect_vec(); + let routes = provider.routes(&mut FakeContext::new()).collect_vec(); assert_eq!( routes, diff --git a/rust/net/infra/src/route/provider.rs b/rust/net/infra/src/route/provider.rs index 899b6cd76..d130bea56 100644 --- a/rust/net/infra/src/route/provider.rs +++ b/rust/net/infra/src/route/provider.rs @@ -45,10 +45,10 @@ pub struct Map(R, F); impl T, T> RouteProvider for Map { type Route = T; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C, R, F, T> { self.0.routes(context).map(&self.1) } } @@ -59,10 +59,10 @@ pub struct Filter(R, F); impl bool> RouteProvider for Filter { type Route = R::Route; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C, R, F> { self.0.routes(context).filter(&self.1) } } @@ -75,10 +75,10 @@ pub struct EmptyProvider { impl RouteProvider for EmptyProvider { type Route = R; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - _context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + _context: &mut C, + ) -> impl Iterator + use<'s, C, R> { std::iter::empty() } } diff --git a/rust/net/infra/src/route/proxy.rs b/rust/net/infra/src/route/proxy.rs index 415b8a1b3..cf206599e 100644 --- a/rust/net/infra/src/route/proxy.rs +++ b/rust/net/infra/src/route/proxy.rs @@ -307,10 +307,10 @@ where { type Route = R; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C, D, R> { let Self { inner, mode } = self; let original_routes = inner.routes(context); match mode { diff --git a/rust/net/infra/src/route/tcp.rs b/rust/net/infra/src/route/tcp.rs index 2fbf2aa76..2fc6b7f9d 100644 --- a/rust/net/infra/src/route/tcp.rs +++ b/rust/net/infra/src/route/tcp.rs @@ -70,10 +70,10 @@ impl DirectTcpRouteProvider { impl RouteProvider for DirectTcpRouteProvider { type Route = TcpRoute; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - _context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + _context: &mut C, + ) -> impl Iterator + use<'s, C> { let Self { dns_hostname, port, diff --git a/rust/net/infra/src/route/tls.rs b/rust/net/infra/src/route/tls.rs index d89491418..6c045f01e 100644 --- a/rust/net/infra/src/route/tls.rs +++ b/rust/net/infra/src/route/tls.rs @@ -64,10 +64,10 @@ pub(crate) trait SetAlpn { impl RouteProvider for TlsRouteProvider

{ type Route = TlsRoute; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C, P> { let Self { sni, certs, diff --git a/rust/net/infra/src/route/ws.rs b/rust/net/infra/src/route/ws.rs index a6b5bfcd9..ec2e3c4e7 100644 --- a/rust/net/infra/src/route/ws.rs +++ b/rust/net/infra/src/route/ws.rs @@ -44,10 +44,10 @@ impl

WebSocketProvider

{ impl RouteProvider for WebSocketProvider

{ type Route = WebSocketRoute; - fn routes<'s>( + fn routes<'s, C: RouteProviderContext>( &'s self, - context: &impl RouteProviderContext, - ) -> impl Iterator + 's { + context: &mut C, + ) -> impl Iterator + use<'s, C, P> { self.inner.routes(context).map(|route| WebSocketRoute { inner: route, fragment: self.fragment.clone(), diff --git a/rust/net/src/cdsi.rs b/rust/net/src/cdsi.rs index 31a82f6ed..0c842ffd3 100644 --- a/rust/net/src/cdsi.rs +++ b/rust/net/src/cdsi.rs @@ -142,20 +142,17 @@ impl TryFrom for LookupResponse { debug_permits_used, } = response; - if e164_pni_aci_triples.len() % LookupResponseEntry::SERIALIZED_LEN != 0 { + let (record_chunks, record_remainder) = + e164_pni_aci_triples.as_chunks::<{ LookupResponseEntry::SERIALIZED_LEN }>(); + + if !record_remainder.is_empty() { return Err(CdsiProtocolError::InvalidNumberOfBytes { actual_length: e164_pni_aci_triples.len(), }); } - - // TODO: Use as_chunks when we reach MSRV 1.88. - let records = e164_pni_aci_triples - .chunks(LookupResponseEntry::SERIALIZED_LEN) - .flat_map(|record| { - LookupResponseEntry::try_parse_from( - record.try_into().expect("chunk size is correct"), - ) - }) + let records = record_chunks + .iter() + .flat_map(LookupResponseEntry::try_parse_from) .collect(); Ok(Self { diff --git a/rust/net/src/chat/ws.rs b/rust/net/src/chat/ws.rs index f40c0039d..c23162809 100644 --- a/rust/net/src/chat/ws.rs +++ b/rust/net/src/chat/ws.rs @@ -441,10 +441,10 @@ impl Responder { pub fn send_response(self, status: StatusCode) -> Result<(), SendError> { let Self { id, tx } = self; - if let Some(tx) = tx.upgrade() { - if let Ok(()) = tx.send(OutgoingResponse { id, status }) { - return Ok(()); - } + if let Some(tx) = tx.upgrade() + && let Ok(()) = tx.send(OutgoingResponse { id, status }) + { + return Ok(()); } Err(SendError::Disconnected(DisconnectedReason::SocketClosed { diff --git a/rust/net/src/connect_state.rs b/rust/net/src/connect_state.rs index 858efd340..2d3b36430 100644 --- a/rust/net/src/connect_state.rs +++ b/rust/net/src/connect_state.rs @@ -506,13 +506,13 @@ impl ConnectionResources<'_, TC> { post_route_change_connect_timeout, transport_connector, attempts_record, - route_provider_context, + mut route_provider_context, } = connect_state .lock() .expect("not poisoned") .prepare_snapshot(); - let routes = routes.routes(&route_provider_context).collect_vec(); + let routes = routes.routes(&mut route_provider_context).collect_vec(); log::info!( "[{log_tag}] starting connection attempt with {} routes", @@ -649,7 +649,7 @@ where post_route_change_connect_timeout, transport_connector, attempts_record, - route_provider_context, + mut route_provider_context, } = connect_state .lock() .expect("not poisoned") @@ -660,7 +660,7 @@ where should: true, inner: r, }) - .routes(&route_provider_context) + .routes(&mut route_provider_context) .collect_vec(); log::info!( @@ -777,7 +777,7 @@ where struct RouteProviderContextImpl(UnwrapErr); impl RouteProviderContext for RouteProviderContextImpl { - fn random_usize(&self) -> usize { + fn random_usize(&mut self) -> usize { // OsRng is zero-sized, so we're not losing random values by copying it. let mut owned_rng: UnwrapErr = self.0; assert_eq_size_val!(owned_rng, ()); diff --git a/rust/net/src/enclave.rs b/rust/net/src/enclave.rs index bed2cb89a..eb1589af5 100644 --- a/rust/net/src/enclave.rs +++ b/rust/net/src/enclave.rs @@ -251,10 +251,10 @@ impl From for Error { response, received_at: _, } => { - if response.status() == http::StatusCode::TOO_MANY_REQUESTS { - if let Some(retry_later) = extract_retry_later(response.headers()) { - return Self::RateLimited(retry_later); - } + if response.status() == http::StatusCode::TOO_MANY_REQUESTS + && let Some(retry_later) = extract_retry_later(response.headers()) + { + return Self::RateLimited(retry_later); } Self::WebSocket(WebSocketError::Http(response)) } diff --git a/rust/net/src/env.rs b/rust/net/src/env.rs index c7ed4acc7..9969277d8 100644 --- a/rust/net/src/env.rs +++ b/rust/net/src/env.rs @@ -962,7 +962,7 @@ mod test { }, override_nagle_algorithm, ); - let routes = route_provider.routes(&FakeContext::new()).collect_vec(); + let routes = route_provider.routes(&mut FakeContext::new()).collect_vec(); let expected_direct_route = HttpsTlsRoute { fragment: HttpRouteFragment { diff --git a/rust/poksho/Cargo.toml b/rust/poksho/Cargo.toml index 44c626450..ea0313cac 100644 --- a/rust/poksho/Cargo.toml +++ b/rust/poksho/Cargo.toml @@ -9,7 +9,7 @@ version = "0.7.0" authors.workspace = true license.workspace = true edition = "2024" -rust-version = "1.85" +rust-version = "1.88" [lints] workspace = true diff --git a/rust/poksho/src/proof.rs b/rust/poksho/src/proof.rs index 92de897e9..2ee97f703 100644 --- a/rust/poksho/src/proof.rs +++ b/rust/poksho/src/proof.rs @@ -19,15 +19,13 @@ impl Proof { /// Returns `None` if the input is invalid. This does not run in constant /// time! pub fn from_slice(bytes: &[u8]) -> Option { - // TODO: use as_chunks instead once we reach MSRV 1.88. - let chunks = bytes.chunks_exact(32); - if !chunks.remainder().is_empty() { + let (chunks, chunks_remainder) = bytes.as_chunks::<32>(); + if !chunks_remainder.is_empty() { return None; } - let mut array_chunks = chunks.map(|chunk| { - let chunk = chunk.try_into().expect("chunk size is exact"); - Option::from(Scalar::from_canonical_bytes(chunk)) - }); + let mut array_chunks = chunks + .iter() + .map(|chunk| Option::from(Scalar::from_canonical_bytes(*chunk))); let challenge = array_chunks.next()??; if array_chunks.len() > 256 { diff --git a/rust/poksho/src/statement.rs b/rust/poksho/src/statement.rs index 6eea1f1d1..ed370c9c3 100644 --- a/rust/poksho/src/statement.rs +++ b/rust/poksho/src/statement.rs @@ -204,13 +204,11 @@ impl Statement { sho2.absorb_and_ratchet(message); // M let blinding_scalar_bytes = sho2.squeeze_and_ratchet(g1.len() * 64); - // TODO: use as_chunks once we reach MSRV 1.88. let nonce: G1 = blinding_scalar_bytes - .chunks_exact(64) - .map(|chunk| { - let chunk = chunk.try_into().expect("correct width"); - Scalar::from_bytes_mod_order_wide(chunk) - }) + .as_chunks::<64>() + .0 + .iter() + .map(Scalar::from_bytes_mod_order_wide) .collect(); // Commitment from nonce by applying homomorphism F: commitment = F(nonce)