Merge pull request #72 from zcash/builder-prep

Builder preparations
This commit is contained in:
Kris Nuttycombe 2021-04-27 07:51:04 -06:00 committed by GitHub
commit 575f882b40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 27 deletions

View File

@ -114,18 +114,46 @@ impl<T> Action<T> {
pub struct Flags { pub struct Flags {
/// Flag denoting whether Orchard spends are enabled in the transaction. /// Flag denoting whether Orchard spends are enabled in the transaction.
/// ///
/// If `true`, spent notes within [`Action`]s in the transaction's [`Bundle`] are /// If `false`, 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 /// guaranteed to be dummy notes. If `true`, the spent notes may be either real or
/// dummy notes. /// dummy notes.
spends_enabled: bool, spends_enabled: bool,
/// Flag denoting whether Orchard outputs are enabled in the transaction. /// Flag denoting whether Orchard outputs are enabled in the transaction.
/// ///
/// If `true`, created notes within [`Action`]s in the transaction's [`Bundle`] are /// If `false`, 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 /// guaranteed to be dummy notes. If `true`, the created notes may be either real or
/// dummy notes. /// dummy notes.
outputs_enabled: bool, 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. /// Defines the authorization type of an Orchard bundle.
pub trait Authorization { pub trait Authorization {
/// The authorization type of an Orchard action. /// The authorization type of an Orchard action.
@ -203,34 +231,36 @@ impl<T: Authorization> Bundle<T> {
} }
/// Transitions this bundle from one authorization state to another. /// Transitions this bundle from one authorization state to another.
pub fn authorize<U: Authorization>( pub fn authorize<R, U: Authorization>(
self, self,
mut spend_auth: impl FnMut(&T, T::SpendAuth) -> U::SpendAuth, context: &mut R,
step: impl FnOnce(T) -> U, mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> U::SpendAuth,
step: impl FnOnce(&mut R, T) -> U,
) -> Bundle<U> { ) -> Bundle<U> {
let authorization = self.authorization; let authorization = self.authorization;
Bundle { Bundle {
actions: self actions: self
.actions .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, flags: self.flags,
value_balance: self.value_balance, value_balance: self.value_balance,
anchor: self.anchor, anchor: self.anchor,
authorization: step(authorization), authorization: step(context, authorization),
} }
} }
/// Transitions this bundle from one authorization state to another. /// Transitions this bundle from one authorization state to another.
pub fn try_authorize<U: Authorization, E>( pub fn try_authorize<R, U: Authorization, E>(
self, self,
mut spend_auth: impl FnMut(&T, T::SpendAuth) -> Result<U::SpendAuth, E>, context: &mut R,
step: impl FnOnce(T) -> Result<U, E>, mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> Result<U::SpendAuth, E>,
step: impl FnOnce(&mut R, T) -> Result<U, E>,
) -> Result<Bundle<U>, E> { ) -> Result<Bundle<U>, E> {
let authorization = self.authorization; let authorization = self.authorization;
let new_actions = self let new_actions = self
.actions .actions
.into_iter() .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::<Result<Vec<_>, E>>()?; .collect::<Result<Vec<_>, E>>()?;
Ok(Bundle { Ok(Bundle {
@ -238,19 +268,11 @@ impl<T: Authorization> Bundle<T> {
flags: self.flags, flags: self.flags,
value_balance: self.value_balance, value_balance: self.value_balance,
anchor: self.anchor, 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. /// Authorizing data for a bundle of actions, ready to be committed to the ledger.
#[derive(Debug)] #[derive(Debug)]
pub struct Authorized { pub struct Authorized {

View File

@ -180,13 +180,13 @@ mod tests {
let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(())
.map(|()| { .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 nf_old = spent_note.nullifier(&fvk);
let ak: SpendValidatingKey = fvk.into(); let ak: SpendValidatingKey = fvk.into();
let alpha = pallas::Scalar::random(&mut rng); let alpha = pallas::Scalar::random(&mut rng);
let rk = ak.randomize(&alpha); 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 cmx = output_note.commitment().into();
let value = spent_note.value() - output_note.value(); let value = spent_note.value() - output_note.value();

View File

@ -65,8 +65,12 @@ impl Note {
/// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes].
/// ///
/// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes
pub(crate) fn dummy(rng: &mut impl RngCore, rho: Option<Nullifier>) -> (FullViewingKey, Self) { pub(crate) fn dummy(
let fvk: FullViewingKey = (&SpendingKey::random(rng)).into(); rng: &mut impl RngCore,
rho: Option<Nullifier>,
) -> (SpendingKey, FullViewingKey, Self) {
let sk = SpendingKey::random(rng);
let fvk: FullViewingKey = (&sk).into();
let recipient = fvk.default_address(); let recipient = fvk.default_address();
let note = Note { let note = Note {
@ -76,7 +80,7 @@ impl Note {
rseed: RandomSeed::random(rng), rseed: RandomSeed::random(rng),
}; };
(fvk, note) (sk, fvk, note)
} }
/// Returns the value of this note. /// Returns the value of this note.

View File

@ -52,6 +52,14 @@ impl NoteValue {
Default::default() 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<Lsb0, [u8; 8]> { pub(crate) fn to_le_bits(self) -> BitArray<Lsb0, [u8; 8]> {
BitArray::<Lsb0, _>::new(self.0.to_le_bytes()) BitArray::<Lsb0, _>::new(self.0.to_le_bytes())
} }
@ -71,6 +79,16 @@ impl Sub for NoteValue {
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct ValueSum(i64); 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 { impl Add for ValueSum {
type Output = Result<ValueSum, OverflowError>; type Output = Result<ValueSum, OverflowError>;