diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs index 1ecb793fb..0bd7f455f 100644 --- a/src/bundle/burn_validation.rs +++ b/src/bundle/burn_validation.rs @@ -67,33 +67,31 @@ impl fmt::Display for BurnError { mod tests { use crate::issuance::compute_asset_desc_hash; use crate::value::NoteValue; + use nonempty::NonEmpty; use super::*; - /// Creates an item of bundle burn list for a given asset description and value. + /// Creates an item of bundle burn list for a given asset description hash and value. /// /// This function is deterministic and guarantees that each call with the same parameters /// will return the same result. It achieves determinism by using a static `IssuanceAuthorizingKey`. /// /// # Arguments /// - /// * `asset_desc` - The asset description string. + /// * `asset_desc_hash` - The asset description hash. /// * `value` - The value for the burn. /// /// # Returns /// /// A tuple `(AssetBase, Amount)` representing the burn list item. /// - pub fn get_burn_tuple(asset_desc: &[u8], value: u64) -> (AssetBase, NoteValue) { + fn get_burn_tuple(asset_desc_hash: &[u8; 32], value: u64) -> (AssetBase, NoteValue) { use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); ( - AssetBase::derive( - &IssuanceValidatingKey::from(&isk), - &compute_asset_desc_hash(asset_desc).unwrap(), - ), + AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc_hash), NoteValue::from_raw(value), ) } @@ -101,9 +99,18 @@ mod tests { #[test] fn validate_bundle_burn_success() { let bundle_burn = vec![ - get_burn_tuple(b"Asset 1", 10), - get_burn_tuple(b"Asset 2", 20), - get_burn_tuple(b"Asset 3", 10), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 1").unwrap()), + 10, + ), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 2").unwrap()), + 20, + ), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 3").unwrap()), + 10, + ), ]; let result = validate_bundle_burn(&bundle_burn); @@ -114,9 +121,18 @@ mod tests { #[test] fn validate_bundle_burn_duplicate_asset() { let bundle_burn = vec![ - get_burn_tuple(b"Asset 1", 10), - get_burn_tuple(b"Asset 1", 20), - get_burn_tuple(b"Asset 3", 10), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 1").unwrap()), + 10, + ), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 1").unwrap()), + 20, + ), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 3").unwrap()), + 10, + ), ]; let result = validate_bundle_burn(&bundle_burn); @@ -127,9 +143,15 @@ mod tests { #[test] fn validate_bundle_burn_native_asset() { let bundle_burn = vec![ - get_burn_tuple(b"Asset 1", 10), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 1").unwrap()), + 10, + ), (AssetBase::native(), NoteValue::from_raw(20)), - get_burn_tuple(b"Asset 3", 10), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 3").unwrap()), + 10, + ), ]; let result = validate_bundle_burn(&bundle_burn); @@ -140,9 +162,18 @@ mod tests { #[test] fn validate_bundle_burn_zero_value() { let bundle_burn = vec![ - get_burn_tuple(b"Asset 1", 10), - get_burn_tuple(b"Asset 2", 0), - get_burn_tuple(b"Asset 3", 10), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 1").unwrap()), + 10, + ), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 2").unwrap()), + 0, + ), + get_burn_tuple( + &compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset 3").unwrap()), + 10, + ), ]; let result = validate_bundle_burn(&bundle_burn); diff --git a/src/issuance.rs b/src/issuance.rs index 1e8217656..8ea0fa8f6 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -13,6 +13,7 @@ //! are handled through the `Error` enum. use alloc::collections::BTreeMap; +use alloc::string::String; use alloc::vec::Vec; use blake2b_simd::{Hash as Blake2bHash, Params}; use core::fmt; @@ -24,7 +25,6 @@ use rand::RngCore; use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; use crate::constants::reference_keys::ReferenceKeys; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; -use crate::note::asset_base::is_asset_desc_of_valid_size; use crate::note::{AssetBase, Nullifier, Rho}; use crate::value::NoteValue; @@ -33,11 +33,10 @@ use crate::{Address, Note}; use crate::asset_record::AssetRecord; use Error::{ - AssetBaseCannotBeIdentityPoint, CannotBeFirstIssuance, InvalidAssetDescHashLength, - IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, - IssueActionWithoutNoteNotFinalized, IssueBundleIkMismatchAssetBase, - IssueBundleInvalidSignature, MissingReferenceNoteOnFirstIssuance, ValueOverflow, - WrongAssetDescSize, + AssetBaseCannotBeIdentityPoint, CannotBeFirstIssuance, IssueActionNotFound, + IssueActionPreviouslyFinalizedAssetBase, IssueActionWithoutNoteNotFinalized, + IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, + MissingReferenceNoteOnFirstIssuance, ValueOverflow, }; /// Checks if a given note is a reference note. @@ -83,19 +82,24 @@ pub struct IssueInfo { } /// Compute the asset description hash for a given asset description. -pub fn compute_asset_desc_hash(asset_desc: &[u8]) -> Result<[u8; 32], Error> { - if !is_asset_desc_of_valid_size(asset_desc) { - return Err(WrongAssetDescSize); +/// +/// # Panics +/// +/// Panics if `asset_desc` is not well-formed as per Unicode 15.0 specification, Section 3.9, D92. +pub fn compute_asset_desc_hash(asset_desc: &NonEmpty) -> [u8; 32] { + if String::from_utf8(asset_desc.iter().copied().collect::>()).is_err() { + panic!("asset_desc is not a well-formed Unicode string"); } let mut ah = Params::new() .hash_length(32) .personal(b"ZSA-AssetDescCRH") .to_state(); - ah.update(asset_desc); + ah.update(&[asset_desc.head]); + ah.update(asset_desc.tail.as_slice()); ah.finalize() .as_bytes() .try_into() - .map_err(|_| InvalidAssetDescHashLength) + .expect("Invalid asset description hash length") } impl IssueAction { @@ -670,10 +674,6 @@ pub enum Error { IssueActionNotFound, /// The provided `isk` and the derived `ik` does not match at least one note type. IssueBundleIkMismatchAssetBase, - /// `asset_desc` should be between 1 and 512 bytes. - WrongAssetDescSize, - /// The length of the asset description hash is invalid. - InvalidAssetDescHashLength, /// The `IssueAction` is not finalized but contains no notes. IssueActionWithoutNoteNotFinalized, /// The `AssetBase` is the Pallas identity point, which is invalid. @@ -706,12 +706,6 @@ impl fmt::Display for Error { "the provided `isk` and the derived `ik` do not match at least one note type" ) } - WrongAssetDescSize => { - write!(f, "`asset_desc` should be between 1 and 512 bytes") - } - InvalidAssetDescHashLength => { - write!(f, "the length of the asset description hash is invalid") - } IssueActionWithoutNoteNotFinalized => { write!( f, @@ -761,7 +755,7 @@ mod tests { issuance::Error::{ AssetBaseCannotBeIdentityPoint, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, - IssueBundleInvalidSignature, WrongAssetDescSize, + IssueBundleInvalidSignature, }, issuance::{ is_reference_note, verify_issue_bundle, AwaitingNullifier, IssueAction, Signed, @@ -851,10 +845,14 @@ mod tests { .. } = setup_params(); - let note1_asset_desc_hash = compute_asset_desc_hash(note1_asset_desc).unwrap(); + let note1_asset_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(note1_asset_desc).unwrap()); let asset = AssetBase::derive(&ik, ¬e1_asset_desc_hash); let note2_asset = note2_asset_desc.map_or(asset, |desc| { - AssetBase::derive(&ik, &compute_asset_desc_hash(desc).unwrap()) + AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(desc).unwrap()), + ) }); let note1 = Note::new( @@ -926,7 +924,7 @@ mod tests { ); let action = IssueAction::from_parts( - compute_asset_desc_hash(b"arbitrary asset_desc").unwrap(), + compute_asset_desc_hash(&NonEmpty::from_slice(b"arbitrary asset_desc").unwrap()), vec![note1, note2], false, ); @@ -1002,15 +1000,8 @@ mod tests { .. } = setup_params(); - let asset_desc_hash_1 = compute_asset_desc_hash(b"Halo").unwrap(); - let asset_desc_hash_2 = compute_asset_desc_hash(b"Halo2").unwrap(); - - assert_eq!( - compute_asset_desc_hash(&vec![b'X'; 513]), - Err(WrongAssetDescSize) - ); - - assert_eq!(compute_asset_desc_hash(b""), Err(WrongAssetDescSize)); + let asset_desc_hash_1 = compute_asset_desc_hash(&NonEmpty::from_slice(b"Halo").unwrap()); + let asset_desc_hash_2 = compute_asset_desc_hash(&NonEmpty::from_slice(b"Halo2").unwrap()); let (mut bundle, asset) = IssueBundle::new( ik.clone(), @@ -1096,8 +1087,9 @@ mod tests { rng, ik, recipient, .. } = setup_params(); - let nft_asset_desc_hash = compute_asset_desc_hash(b"NFT").unwrap(); - let another_nft_asset_desc_hash = compute_asset_desc_hash(b"Another NFT").unwrap(); + let nft_asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(b"NFT").unwrap()); + let another_nft_asset_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"Another NFT").unwrap()); let (mut bundle, _) = IssueBundle::new( ik, @@ -1133,7 +1125,7 @@ mod tests { .. } = setup_params(); - let asset_desc_hash = compute_asset_desc_hash(b"Frost").unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(b"Frost").unwrap()); let (bundle, _) = IssueBundle::new( ik, @@ -1161,7 +1153,7 @@ mod tests { first_nullifier, } = setup_params(); - let asset_desc_hash = compute_asset_desc_hash(b"Sign").unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(b"Sign").unwrap()); let (bundle, _) = IssueBundle::new( ik.clone(), @@ -1194,7 +1186,8 @@ mod tests { .. } = setup_params(); - let asset_desc_hash = compute_asset_desc_hash(b"IssueBundle").unwrap(); + let asset_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"IssueBundle").unwrap()); let (bundle, _) = IssueBundle::new( ik, @@ -1232,7 +1225,7 @@ mod tests { // Create a bundle with "normal" note let (mut bundle, _) = IssueBundle::new( ik, - compute_asset_desc_hash(b"IssueBundle").unwrap(), + compute_asset_desc_hash(&NonEmpty::from_slice(b"IssueBundle").unwrap()), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1245,7 +1238,10 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - AssetBase::derive(bundle.ik(), &compute_asset_desc_hash(b"zsa_asset").unwrap()), + AssetBase::derive( + bundle.ik(), + &compute_asset_desc_hash(&NonEmpty::from_slice(b"zsa_asset").unwrap()), + ), Rho::zero(), &mut rng, ); @@ -1271,7 +1267,7 @@ mod tests { first_nullifier, } = setup_params(); - let asset_desc_hash = compute_asset_desc_hash(b"Verify").unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(b"Verify").unwrap()); let (bundle, _) = IssueBundle::new( ik.clone(), @@ -1313,7 +1309,8 @@ mod tests { first_nullifier, } = setup_params(); - let asset_desc_hash = compute_asset_desc_hash(b"Verify with finalize").unwrap(); + let asset_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"Verify with finalize").unwrap()); let (mut bundle, _) = IssueBundle::new( ik.clone(), @@ -1357,9 +1354,12 @@ mod tests { first_nullifier, } = setup_params(); - let asset1_desc_hash = compute_asset_desc_hash(b"Verify with issued assets 1").unwrap(); - let asset2_desc_hash = compute_asset_desc_hash(b"Verify with issued assets 2").unwrap(); - let asset3_desc_hash = compute_asset_desc_hash(b"Verify with issued assets 3").unwrap(); + let asset1_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"Verify with issued assets 1").unwrap()); + let asset2_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"Verify with issued assets 2").unwrap()); + let asset3_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"Verify with issued assets 3").unwrap()); let asset1_base = AssetBase::derive(&ik, &asset1_desc_hash); let asset2_base = AssetBase::derive(&ik, &asset2_desc_hash); @@ -1461,7 +1461,8 @@ mod tests { first_nullifier, } = setup_params(); - let asset_desc_hash = compute_asset_desc_hash(b"already final").unwrap(); + let asset_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"already final").unwrap()); let (bundle, _) = IssueBundle::new( ik.clone(), @@ -1526,7 +1527,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - crate::issuance::compute_asset_desc_hash(b"bad sig").unwrap(), + crate::issuance::compute_asset_desc_hash(&NonEmpty::from_slice(b"bad sig").unwrap()), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1566,7 +1567,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - compute_asset_desc_hash(b"Asset description").unwrap(), + compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset description").unwrap()), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1601,7 +1602,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - compute_asset_desc_hash(b"Asset description").unwrap(), + compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset description").unwrap()), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1620,7 +1621,10 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - AssetBase::derive(signed.ik(), &compute_asset_desc_hash(b"zsa_asset").unwrap()), + AssetBase::derive( + signed.ik(), + &compute_asset_desc_hash(&NonEmpty::from_slice(b"zsa_asset").unwrap()), + ), Rho::zero(), &mut rng, ); @@ -1635,7 +1639,7 @@ mod tests { #[test] fn issue_bundle_verify_fail_incorrect_ik() { - let asset_desc_hash = compute_asset_desc_hash(b"Asset").unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset").unwrap()); let TestParams { mut rng, @@ -1720,7 +1724,8 @@ mod tests { let mut rng = OsRng; let (_, _, note) = Note::dummy(&mut rng, None, AssetBase::native()); - let asset_desc_hash = compute_asset_desc_hash(b"Asset description").unwrap(); + let asset_desc_hash = + compute_asset_desc_hash(&NonEmpty::from_slice(b"Asset description").unwrap()); let action = IssueAction::new_with_flags(asset_desc_hash, vec![note], 0u8).unwrap(); assert_eq!(action.flags(), 0b0000_0000); @@ -1733,7 +1738,7 @@ mod tests { } #[test] - fn issue_bundle_asset_desc_roundtrip() { + fn test_get_action_by_desc_hash() { let TestParams { rng, ik, recipient, .. } = setup_params(); @@ -1741,17 +1746,10 @@ mod tests { // UTF heavy test string let asset_desc_1 = "ฮฉฮฃ๐ทเค•ใ‚ํ•œ๐Ÿโ˜…โ†’".to_string().as_bytes().to_vec(); - let asset_desc_hash_1 = compute_asset_desc_hash(&asset_desc_1).unwrap(); - - // Not well-formed as per Unicode 15.0 specification, Section 3.9, D92 - let asset_desc_2: Vec = vec![0xc0, 0xaf]; - - let asset_desc_hash_2 = compute_asset_desc_hash(&asset_desc_2).unwrap(); + let asset_desc_hash_1 = + compute_asset_desc_hash(&NonEmpty::from_slice(&asset_desc_1).unwrap()); - // Confirm not valid UTF-8 - assert!(String::from_utf8(asset_desc_2.clone()).is_err()); - - let (mut bundle, asset_base_1) = IssueBundle::new( + let (bundle, asset_base_1) = IssueBundle::new( ik, asset_desc_hash_1, Some(IssueInfo { @@ -1762,16 +1760,6 @@ mod tests { rng, ); - let asset_base_2 = bundle - .add_recipient( - asset_desc_hash_2, - recipient, - NoteValue::from_raw(10), - true, - rng, - ) - .unwrap(); - // Checks for the case of UTF-8 encoded asset description. let action = bundle.get_action_by_asset(&asset_base_1).unwrap(); assert_eq!(action.asset_desc_hash(), &asset_desc_hash_1); @@ -1782,17 +1770,19 @@ mod tests { bundle.get_action_by_desc_hash(&asset_desc_hash_1).unwrap(), action ); + } - // Checks for the case on non-UTF-8 encoded asset description. - let action2 = bundle.get_action_by_asset(&asset_base_2).unwrap(); - assert_eq!(action2.asset_desc_hash(), &asset_desc_hash_2); - let reference_note = action2.notes.first().unwrap(); - verify_reference_note(reference_note, asset_base_2); - assert_eq!(action2.notes.get(1).unwrap().value().inner(), 10); - assert_eq!( - bundle.get_action_by_desc_hash(&asset_desc_hash_2).unwrap(), - action2 - ); + #[test] + #[should_panic(expected = "asset_desc is not a well-formed Unicode string")] + fn not_well_formed_utf8() { + // Not well-formed as per Unicode 15.0 specification, Section 3.9, D92 + let asset_desc: Vec = vec![0xc0, 0xaf]; + + // Confirm not valid UTF-8 + assert!(String::from_utf8(asset_desc.clone()).is_err()); + + // Should panic + compute_asset_desc_hash(&NonEmpty::from_slice(&asset_desc).unwrap()); } #[test] @@ -1807,7 +1797,10 @@ mod tests { // Setup note and merkle tree let mut rng = OsRng; - let asset1 = AssetBase::derive(&ik, &compute_asset_desc_hash(b"zsa_asset1").unwrap()); + let asset1 = AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(b"zsa_asset1").unwrap()), + ); let note1 = Note::new( recipient, NoteValue::from_raw(10), @@ -1857,8 +1850,8 @@ mod tests { .unwrap(); // Create an issue bundle - let asset_desc_hash_2 = compute_asset_desc_hash(b"asset2").unwrap(); - let asset_desc_hash_3 = compute_asset_desc_hash(b"asset3").unwrap(); + let asset_desc_hash_2 = compute_asset_desc_hash(&NonEmpty::from_slice(b"asset2").unwrap()); + let asset_desc_hash_3 = compute_asset_desc_hash(&NonEmpty::from_slice(b"asset3").unwrap()); let (mut bundle, asset) = IssueBundle::new( ik, asset_desc_hash_2, diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 6d9c2a9d3..d73cf8823 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -2,6 +2,7 @@ use blake2b_simd::{Hash as Blake2bHash, Params}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use group::{Curve, Group, GroupEncoding}; +use nonempty::NonEmpty; use pasta_curves::arithmetic::CurveAffine; use pasta_curves::{arithmetic::CurveExt, pallas}; use rand_core::CryptoRngCore; @@ -37,8 +38,6 @@ impl Ord for AssetBase { } } -pub const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; - /// Personalization for the ZSA asset digest generator pub const ZSA_ASSET_DIGEST_PERSONALIZATION: &[u8; 16] = b"ZSA-Asset-Digest"; @@ -127,7 +126,10 @@ impl AssetBase { pub(crate) fn random(rng: &mut impl CryptoRngCore) -> Self { let isk = IssuanceAuthorizingKey::random(rng); let ik = IssuanceValidatingKey::from(&isk); - AssetBase::derive(&ik, &compute_asset_desc_hash(b"zsa_asset").unwrap()) + AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(b"zsa_asset").unwrap()), + ) } } @@ -138,11 +140,6 @@ impl Hash for AssetBase { } } -/// Check that `asset_desc` is of valid size. -pub fn is_asset_desc_of_valid_size(asset_desc: &[u8]) -> bool { - !asset_desc.is_empty() && asset_desc.len() <= MAX_ASSET_DESCRIPTION_SIZE -} - impl PartialEq for AssetBase { fn eq(&self, other: &Self) -> bool { bool::from(self.0.ct_eq(&other.0)) @@ -206,8 +203,9 @@ pub mod testing { let test_vectors = crate::test_vectors::asset_base::TEST_VECTORS; for tv in test_vectors { - let asset_desc_hash = - crate::issuance::compute_asset_desc_hash(&tv.description).unwrap(); + let asset_desc_hash = crate::issuance::compute_asset_desc_hash( + &nonempty::NonEmpty::from_slice(&tv.description).unwrap(), + ); let calculated_asset_base = AssetBase::derive( &IssuanceValidatingKey::from_bytes(&tv.key).unwrap(), &asset_desc_hash, diff --git a/tests/issuance_global_state.rs b/tests/issuance_global_state.rs index 86214e97a..94b51df56 100644 --- a/tests/issuance_global_state.rs +++ b/tests/issuance_global_state.rs @@ -1,7 +1,7 @@ extern crate alloc; use alloc::collections::BTreeMap; - +use nonempty::NonEmpty; use rand::{rngs::OsRng, RngCore}; use orchard::{ @@ -128,7 +128,7 @@ fn build_issue_bundle(params: &TestParams, data: &[IssueTestNote]) -> IssueBundl first_issuance, } = data.first().unwrap().clone(); - let asset_desc_hash = compute_asset_desc_hash(&asset_desc).unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(&asset_desc).unwrap()); let (mut bundle, _) = IssueBundle::new( ik.clone(), @@ -152,7 +152,7 @@ fn build_issue_bundle(params: &TestParams, data: &[IssueTestNote]) -> IssueBundl first_issuance, } in data.iter().skip(1).cloned() { - let asset_desc_hash = compute_asset_desc_hash(&asset_desc).unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(&asset_desc).unwrap()); bundle .add_recipient( asset_desc_hash, @@ -188,10 +188,22 @@ fn issue_bundle_verify_with_global_state() { let asset3_desc = b"Verify with issued assets 3".to_vec(); let asset4_desc = b"Verify with issued assets 4".to_vec(); - let asset1_base = AssetBase::derive(&ik, &compute_asset_desc_hash(&asset1_desc).unwrap()); - let asset2_base = AssetBase::derive(&ik, &compute_asset_desc_hash(&asset2_desc).unwrap()); - let asset3_base = AssetBase::derive(&ik, &compute_asset_desc_hash(&asset3_desc).unwrap()); - let asset4_base = AssetBase::derive(&ik, &compute_asset_desc_hash(&asset4_desc).unwrap()); + let asset1_base = AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(&asset1_desc).unwrap()), + ); + let asset2_base = AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(&asset2_desc).unwrap()), + ); + let asset3_base = AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(&asset3_desc).unwrap()), + ); + let asset4_base = AssetBase::derive( + &ik, + &compute_asset_desc_hash(&NonEmpty::from_slice(&asset4_desc).unwrap()), + ); let mut global_state = BTreeMap::new(); diff --git a/tests/zsa.rs b/tests/zsa.rs index 43628706b..2419efa5e 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -2,6 +2,7 @@ mod builder; use crate::builder::verify_bundle; use incrementalmerkletree::{Hashable, Marking, Retention}; +use nonempty::NonEmpty; use orchard::bundle::Authorized; use orchard::issuance::{ compute_asset_desc_hash, verify_issue_bundle, AwaitingNullifier, IssueBundle, IssueInfo, Signed, @@ -160,7 +161,7 @@ fn issue_zsa_notes( ) -> (Note, Note, Note) { let mut rng = OsRng; // Create a issuance bundle - let asset_desc_hash = compute_asset_desc_hash(asset_descr).unwrap(); + let asset_desc_hash = compute_asset_desc_hash(&NonEmpty::from_slice(asset_descr).unwrap()); let (mut awaiting_nullifier_bundle, _) = IssueBundle::new( keys.ik().clone(), asset_desc_hash,