From 43c851bc841bccc65ffddab7205783c43f25417f Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Thu, 14 Mar 2024 13:50:56 +0200 Subject: refactor(nix-compat/store_path): take [u8;32] for outer fingerprint The outer fingerprint used for store path calculation is always a sha256 digest. This includes both input and output-addressed store paths. We used a NixHash here, which can also represent other hash types, and that had a bunch of annoyances: - Whenever we had the bytes, we had to wrap them in a NixHash::Sha256(). - Things like AtermWriteable had to be implemented on NixHash, even though we then had an assertion it was only called in the NixHash::Sha256 case. Change-Id: Ic895503d9b071800d2e52ae057666f44bd0ab9d6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11142 Tested-by: BuildkiteCI Autosubmit: flokli Reviewed-by: John Ericson Reviewed-by: picnoir picnoir --- tvix/nix-compat/src/store_path/utils.rs | 39 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'tvix/nix-compat/src/store_path/utils.rs') diff --git a/tvix/nix-compat/src/store_path/utils.rs b/tvix/nix-compat/src/store_path/utils.rs index 2289594e3a10..d054d5955696 100644 --- a/tvix/nix-compat/src/store_path/utils.rs +++ b/tvix/nix-compat/src/store_path/utils.rs @@ -1,8 +1,8 @@ use crate::nixbase32; use crate::nixhash::{CAHash, NixHash}; use crate::store_path::{Error, StorePathRef, DIGEST_SIZE, STORE_DIR}; +use data_encoding::HEXLOWER; use sha2::{Digest, Sha256}; -use std::io::Write; use thiserror; /// Errors that can occur when creating a content-addressed store path. @@ -66,14 +66,11 @@ pub fn build_ca_path<'a, S: AsRef, I: IntoIterator>( return Err(BuildStorePathError::InvalidReference()); } - let (ty, hash) = match &ca_hash { - CAHash::Text(ref digest) => ( - make_references_string("text", references, false), - NixHash::Sha256(*digest), - ), + let (ty, inner_digest) = match &ca_hash { + CAHash::Text(ref digest) => (make_references_string("text", references, false), *digest), CAHash::Nar(NixHash::Sha256(ref digest)) => ( make_references_string("source", references, self_reference), - NixHash::Sha256(*digest), + *digest, ), // for all other CAHash::Nar, another custom scheme is used. @@ -84,7 +81,7 @@ pub fn build_ca_path<'a, S: AsRef, I: IntoIterator>( ( "output:out".to_string(), - NixHash::Sha256(fixed_out_digest("fixed:out:r", hash)), + fixed_out_digest("fixed:out:r", hash), ) } // CaHash::Flat is using something very similar, except the `r:` prefix. @@ -95,12 +92,12 @@ pub fn build_ca_path<'a, S: AsRef, I: IntoIterator>( ( "output:out".to_string(), - NixHash::Sha256(fixed_out_digest("fixed:out", hash)), + fixed_out_digest("fixed:out", hash), ) } }; - build_store_path_from_fingerprint_parts(&ty, &hash, name) + build_store_path_from_fingerprint_parts(&ty, &inner_digest, name) .map_err(BuildStorePathError::InvalidStorePath) } @@ -128,13 +125,13 @@ pub fn build_nar_based_store_path<'a>( /// Input-addresed store paths are always derivation outputs, the "input" in question is the /// derivation and its closure. pub fn build_output_path<'a>( - drv_hash: &NixHash, + drv_sha256: &[u8; 32], output_name: &str, output_path_name: &'a str, ) -> Result, Error> { build_store_path_from_fingerprint_parts( &(String::from("output:") + output_name), - drv_hash, + drv_sha256, output_path_name, ) } @@ -145,18 +142,20 @@ pub fn build_output_path<'a>( /// but other fingerprints starting with "output:" are also used in Derivation /// output path calculation. /// -/// The fingerprint is hashed with sha256, its digest is compressed to 20 bytes, -/// and nixbase32-encoded (32 characters). +/// The fingerprint is hashed with sha256, and its digest is compressed to 20 +/// bytes. +/// Inside a StorePath, that digest is printed nixbase32-encoded +/// (32 characters). fn build_store_path_from_fingerprint_parts<'a>( ty: &str, - hash: &NixHash, + inner_digest: &[u8; 32], name: &'a str, ) -> Result, Error> { - let digest: [u8; DIGEST_SIZE] = compress_hash(&{ - let mut h = Sha256::new(); - write!(h, "{ty}:{}:{STORE_DIR}:{name}", hash.to_nix_hex_string()).unwrap(); - h.finalize() - }); + let fingerprint = format!( + "{ty}:sha256:{}:{STORE_DIR}:{name}", + HEXLOWER.encode(inner_digest) + ); + let digest: [u8; DIGEST_SIZE] = compress_hash(&Sha256::new_with_prefix(fingerprint).finalize()); // name validation happens in here. StorePathRef::from_name_and_digest(name, &digest) -- cgit 1.4.1