Skip to content

Commit d09fbcc

Browse files
committed
feat: Add support for multiple digest functions with backward compatibility
1 parent f672af7 commit d09fbcc

3 files changed

Lines changed: 63 additions & 3 deletions

File tree

nativelink-store/src/grpc_store.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use nativelink_util::origin_context::ActiveOriginContext;
4545
use nativelink_util::proto_stream_utils::{
4646
FirstStream, WriteRequestStreamWrapper, WriteState, WriteStateWrapper,
4747
};
48-
use nativelink_util::resource_info::ResourceInfo;
48+
use nativelink_util::resource_info::{is_supported_digest_function, ResourceInfo};
4949
use nativelink_util::retry::{Retrier, RetryResult};
5050
use nativelink_util::store_trait::{StoreDriver, StoreKey, UploadSizeInfo};
5151
use nativelink_util::{default_health_status_indicator, tls_utils};
@@ -276,12 +276,28 @@ impl GrpcStore {
276276
&self,
277277
grpc_request: impl IntoRequest<ReadRequest>,
278278
) -> Result<impl Stream<Item = Result<ReadResponse, Status>>, Error> {
279+
const IS_UPLOAD_FALSE: bool = false;
280+
281+
let request = self.get_read_request(grpc_request.into_request().into_inner())?;
282+
let resource_name = &request.resource_name;
283+
let resource_info = ResourceInfo::new(resource_name, IS_UPLOAD_FALSE)
284+
.err_tip(|| "Failed to parse resource_name in GrpcStore::read")?;
285+
286+
let digest_function = resource_info.digest_function.as_deref().unwrap_or("sha256");
287+
288+
if !is_supported_digest_function(digest_function) {
289+
return Err(make_input_err!(
290+
"Unsupported digest_function: {} in resource_name '{}'",
291+
digest_function,
292+
resource_name
293+
));
294+
}
295+
279296
error_if!(
280297
matches!(self.store_type, nativelink_config::stores::StoreType::ac),
281298
"CAS operation on AC store"
282299
);
283300

284-
let request = self.get_read_request(grpc_request.into_request().into_inner())?;
285301
self.perform_request(request, |request| async move {
286302
self.read_internal(request).await
287303
})
@@ -514,6 +530,18 @@ impl StoreDriver for GrpcStore {
514530
keys: &[StoreKey<'_>],
515531
results: &mut [Option<u64>],
516532
) -> Result<(), Error> {
533+
let digest_function = ActiveOriginContext::get_value(&ACTIVE_HASHER_FUNC)
534+
.err_tip(|| "In GrpcStore::has_with_results")?
535+
.map_or_else(default_digest_hasher_func, |v| *v)
536+
.to_string();
537+
538+
if !is_supported_digest_function(&digest_function) {
539+
return Err(make_input_err!(
540+
"Unsupported digest_function: {}",
541+
digest_function
542+
));
543+
}
544+
517545
if matches!(self.store_type, nativelink_config::stores::StoreType::ac) {
518546
keys.iter()
519547
.zip(results.iter_mut())

nativelink-util/src/resource_info.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ enum State {
206206
OptionalMetadata,
207207
}
208208

209+
pub fn is_supported_digest_function(digest_function: &str) -> bool {
210+
DIGEST_FUNCTIONS.contains(&digest_function.to_lowercase().as_str())
211+
}
212+
209213
// Iterate backwards looking for "(compressed-)blobs", once found, move forward
210214
// populating the output struct. This recursive function utilises the stack to
211215
// temporarily hold the reference to the previous item reducing the need for

nativelink-util/tests/resource_info_test.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use std::borrow::Cow;
1616

1717
use nativelink_macro::nativelink_test;
18-
use nativelink_util::resource_info::ResourceInfo;
18+
use nativelink_util::resource_info::{is_supported_digest_function, ResourceInfo};
1919
use pretty_assertions::assert_eq;
2020

2121
#[nativelink_test]
@@ -707,3 +707,31 @@ async fn write_invalid_size_test() -> Result<(), Box<dyn std::error::Error>> {
707707
assert!(ResourceInfo::new(RESOURCE_NAME, true).is_err());
708708
Ok(())
709709
}
710+
711+
#[nativelink_test]
712+
async fn test_supported_digest_functions() -> Result<(), Box<dyn std::error::Error>> {
713+
assert_eq!(is_supported_digest_function("sha256"), true);
714+
assert_eq!(is_supported_digest_function("sha1"), true);
715+
assert_eq!(is_supported_digest_function("md5"), true);
716+
assert_eq!(is_supported_digest_function("vso"), true);
717+
assert_eq!(is_supported_digest_function("sha384"), true);
718+
assert_eq!(is_supported_digest_function("sha512"), true);
719+
assert_eq!(is_supported_digest_function("murmur3"), true);
720+
assert_eq!(is_supported_digest_function("sha256tree"), true);
721+
assert_eq!(is_supported_digest_function("blake3"), true);
722+
723+
Ok(())
724+
}
725+
726+
#[nativelink_test]
727+
async fn test_unsupported_digest_functions() -> Result<(), Box<dyn std::error::Error>> {
728+
assert_eq!(is_supported_digest_function("sha3"), false);
729+
assert_eq!(
730+
is_supported_digest_function("invalid_digest_function"),
731+
false
732+
);
733+
assert_eq!(is_supported_digest_function("boo"), false);
734+
assert_eq!(is_supported_digest_function("random_hash"), false);
735+
736+
Ok(())
737+
}

0 commit comments

Comments
 (0)