diff --git a/src/bundle.rs b/src/bundle.rs index 96964a02..5141b472 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -114,18 +114,46 @@ impl Action { pub struct Flags { /// Flag denoting whether Orchard spends are enabled in the transaction. /// - /// If `true`, spent notes within [`Action`]s in the transaction's [`Bundle`] are - /// guaranteed to be dummy notes. If `false`, the spent notes may be either real or + /// If `false`, spent notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be dummy notes. If `true`, the spent notes may be either real or /// dummy notes. spends_enabled: bool, /// Flag denoting whether Orchard outputs are enabled in the transaction. /// - /// If `true`, created notes within [`Action`]s in the transaction's [`Bundle`] are - /// guaranteed to be dummy notes. If `false`, the created notes may be either real or + /// If `false`, created notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be dummy notes. If `true`, the created notes may be either real or /// dummy notes. outputs_enabled: bool, } +impl Flags { + /// Construct a set of flags from its constituent parts + pub fn from_parts(spends_enabled: bool, outputs_enabled: bool) -> Self { + Flags { + spends_enabled, + outputs_enabled, + } + } + + /// Flag denoting whether Orchard spends are enabled in the transaction. + /// + /// If `false`, spent notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be dummy notes. If `true`, the spent notes may be either real or + /// dummy notes. + pub fn spends_enabled(&self) -> bool { + self.spends_enabled + } + + /// Flag denoting whether Orchard outputs are enabled in the transaction. + /// + /// If `false`, created notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be dummy notes. If `true`, the created notes may be either real or + /// dummy notes. + pub fn outputs_enabled(&self) -> bool { + self.outputs_enabled + } +} + /// Defines the authorization type of an Orchard bundle. pub trait Authorization { /// The authorization type of an Orchard action. @@ -203,34 +231,36 @@ impl Bundle { } /// Transitions this bundle from one authorization state to another. - pub fn authorize( + pub fn authorize( self, - mut spend_auth: impl FnMut(&T, T::SpendAuth) -> U::SpendAuth, - step: impl FnOnce(T) -> U, + context: &mut R, + mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> U::SpendAuth, + step: impl FnOnce(&mut R, T) -> U, ) -> Bundle { let authorization = self.authorization; Bundle { actions: self .actions - .map(|a| a.map(|a_auth| spend_auth(&authorization, a_auth))), + .map(|a| a.map(|a_auth| spend_auth(context, &authorization, a_auth))), flags: self.flags, value_balance: self.value_balance, anchor: self.anchor, - authorization: step(authorization), + authorization: step(context, authorization), } } /// Transitions this bundle from one authorization state to another. - pub fn try_authorize( + pub fn try_authorize( self, - mut spend_auth: impl FnMut(&T, T::SpendAuth) -> Result, - step: impl FnOnce(T) -> Result, + context: &mut R, + mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> Result, + step: impl FnOnce(&mut R, T) -> Result, ) -> Result, E> { let authorization = self.authorization; let new_actions = self .actions .into_iter() - .map(|a| a.try_map(|a_auth| spend_auth(&authorization, a_auth))) + .map(|a| a.try_map(|a_auth| spend_auth(context, &authorization, a_auth))) .collect::, E>>()?; Ok(Bundle { @@ -238,19 +268,11 @@ impl Bundle { flags: self.flags, value_balance: self.value_balance, anchor: self.anchor, - authorization: step(authorization)?, + authorization: step(context, authorization)?, }) } } -/// Marker for an unauthorized bundle with no proofs or signatures. -#[derive(Debug)] -pub struct Unauthorized {} - -impl Authorization for Unauthorized { - type SpendAuth = (); -} - /// Authorizing data for a bundle of actions, ready to be committed to the ledger. #[derive(Debug)] pub struct Authorized { diff --git a/src/circuit.rs b/src/circuit.rs index b993f845..2bf53bc2 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -180,13 +180,13 @@ mod tests { let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) .map(|()| { - let (fvk, spent_note) = Note::dummy(&mut rng, None); + let (_, fvk, spent_note) = Note::dummy(&mut rng, None); let nf_old = spent_note.nullifier(&fvk); let ak: SpendValidatingKey = fvk.into(); let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let (_, output_note) = Note::dummy(&mut rng, Some(nf_old.clone())); + let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old.clone())); let cmx = output_note.commitment().into(); let value = spent_note.value() - output_note.value(); diff --git a/src/note.rs b/src/note.rs index 417e665b..39227cf1 100644 --- a/src/note.rs +++ b/src/note.rs @@ -65,8 +65,12 @@ impl Note { /// Defined in [Zcash Protocol Spec ยง 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - pub(crate) fn dummy(rng: &mut impl RngCore, rho: Option) -> (FullViewingKey, Self) { - let fvk: FullViewingKey = (&SpendingKey::random(rng)).into(); + pub(crate) fn dummy( + rng: &mut impl RngCore, + rho: Option, + ) -> (SpendingKey, FullViewingKey, Self) { + let sk = SpendingKey::random(rng); + let fvk: FullViewingKey = (&sk).into(); let recipient = fvk.default_address(); let note = Note { @@ -76,7 +80,7 @@ impl Note { rseed: RandomSeed::random(rng), }; - (fvk, note) + (sk, fvk, note) } /// Returns the value of this note. diff --git a/src/value.rs b/src/value.rs index 75fe837c..ce1ae43c 100644 --- a/src/value.rs +++ b/src/value.rs @@ -52,6 +52,14 @@ impl NoteValue { Default::default() } + /// Creates a note value from its raw numeric value. + /// + /// This only enforces that the value is an unsigned 64-bit integer. Callers should + /// enforce any additional constraints on the value's valid range themselves. + pub fn from_raw(value: u64) -> Self { + NoteValue(value) + } + pub(crate) fn to_le_bits(self) -> BitArray { BitArray::::new(self.0.to_le_bytes()) } @@ -71,6 +79,16 @@ impl Sub for NoteValue { #[derive(Clone, Copy, Debug, Default)] pub struct ValueSum(i64); +impl ValueSum { + /// Creates a value sum from its raw numeric value. + /// + /// This only enforces that the value is a signed 63-bit integer. Callers should + /// enforce any additional constraints on the value's valid range themselves. + pub fn from_raw(value: i64) -> Self { + ValueSum(value) + } +} + impl Add for ValueSum { type Output = Result;