diff --git a/src/builder.rs b/src/builder.rs index fb65ed0b8..cc7073966 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -113,7 +113,9 @@ impl BundleType { pub fn flags(&self) -> Flags { match self { BundleType::Transactional { flags, .. } => *flags, - BundleType::Coinbase => Flags::SPENDS_DISABLED, + // FIXME: is it correct to use SPENDS_DISABLED_WITHOUT_ZSA (i.e does coinbase always have + // ZSA disabled)? + BundleType::Coinbase => Flags::SPENDS_DISABLED_WITHOUT_ZSA, } } } diff --git a/src/bundle.rs b/src/bundle.rs index 4cc1b50a1..594ce9099 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -100,13 +100,20 @@ impl Flags { zsa_enabled: true, }; - /// The flag set with spends disabled. - pub const SPENDS_DISABLED: Flags = Flags { + /// The flag set with spends and ZSA disabled. + pub const SPENDS_DISABLED_WITHOUT_ZSA: Flags = Flags { spends_enabled: false, outputs_enabled: true, zsa_enabled: false, }; + /// The flag set with spends disabled and ZSA enabled. + pub const SPENDS_DISABLED_WITH_ZSA: Flags = Flags { + spends_enabled: false, + outputs_enabled: true, + zsa_enabled: true, + }; + /// The flag set with outputs disabled. pub const OUTPUTS_DISABLED: Flags = Flags { spends_enabled: true, diff --git a/tests/builder.rs b/tests/builder.rs index 9168123cb..72fb7dd88 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -68,7 +68,10 @@ fn bundle_chain() { let mut builder = Builder::new( BundleType::Transactional { - flags: Flags::SPENDS_DISABLED, + // FIXME: Should we use SPENDS_DISABLED_WITH_ZSA for FL=OrchardZSA case? + // The original zsa1 code used the following: + // let mut builder = Builder::new(Flags::from_parts(false, true, false), anchor); + flags: Flags::SPENDS_DISABLED_WITHOUT_ZSA, bundle_required: false, }, anchor, @@ -100,20 +103,44 @@ fn bundle_chain() { // Verify the shielding bundle. verify_bundle(&shielding_bundle, &vk, true); - // Create a shielded bundle spending the previous output. - let shielded_bundle: Bundle<_, i64, FL> = { + let note = { let ivk = PreparedIncomingViewingKey::new(&fvk.to_ivk(Scope::External)); - let (note, _, _) = shielding_bundle + shielding_bundle .actions() .iter() .find_map(|action| { let domain = OrchardDomain::for_action(action); try_note_decryption(&domain, &ivk, action) }) - .unwrap(); + .unwrap() + .0 + }; + // Test that spend adding attempt fails when spends are disabled. + // Note: We do not need a separate positive test for spends enabled + // as the following code adds spends with spends enabled. + { + let (merkle_path, anchor) = build_merkle_path(¬e); + + let mut builder = Builder::new( + BundleType::Transactional { + // FIXME: Should we use SPENDS_DISABLED_WITH_ZSA for FL=OrchardZSA case? + flags: Flags::SPENDS_DISABLED_WITHOUT_ZSA, + bundle_required: false, + }, + anchor, + ); + + assert!(builder.add_spend(fvk.clone(), note, merkle_path).is_err()); + } + + // Create a shielded bundle spending the previous output. + let shielded_bundle: Bundle<_, i64, FL> = { let (merkle_path, anchor) = build_merkle_path(¬e); + // FIXME: Should we use DEFAULT_ZSA for FL=OrchardZSA case? + // The original zsa1 code used the following: + // let mut builder = Builder::new(Flags::from_parts(true, true, false), anchor); let mut builder = Builder::new(BundleType::DEFAULT_VANILLA, anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!(