Apply suggestions from code review

Co-authored-by: str4d <thestr4d@gmail.com>
This commit is contained in:
Kris Nuttycombe 2023-12-19 12:18:31 -07:00 committed by Kris Nuttycombe
parent 2e2c161d52
commit 938b203de5
1 changed files with 32 additions and 16 deletions

View File

@ -27,7 +27,7 @@ use crate::{
const MIN_ACTIONS: usize = 2; const MIN_ACTIONS: usize = 2;
/// An enumeration of rules Orchard bundle construction. /// An enumeration of rules for Orchard bundle construction.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BundleType { pub enum BundleType {
/// A transactional bundle will be padded if necessary to contain at least 2 actions, /// A transactional bundle will be padded if necessary to contain at least 2 actions,
@ -60,7 +60,13 @@ impl BundleType {
Ok(core::cmp::max(num_requested_actions, MIN_ACTIONS)) Ok(core::cmp::max(num_requested_actions, MIN_ACTIONS))
} }
} }
BundleType::Coinbase => Ok(num_outputs), BundleType::Coinbase => {
if num_spends > 0 {
Err("Coinbase bundles have spends disabled, so num_spends must be zero")
} else {
Ok(num_outputs)
}
}
} }
} }
@ -80,7 +86,7 @@ pub enum BuildError {
SpendsDisabled, SpendsDisabled,
/// Spends are disabled for the provided bundle type. /// Spends are disabled for the provided bundle type.
OutputsDisabled, OutputsDisabled,
/// The anchor provided to this builder doesn't match the merkle path used to add a spend. /// The anchor provided to this builder doesn't match the Merkle path used to add a spend.
AnchorMismatch, AnchorMismatch,
/// A bundle could not be built because required signatures were missing. /// A bundle could not be built because required signatures were missing.
MissingSignatures, MissingSignatures,
@ -217,6 +223,16 @@ impl SpendInfo {
merkle_path, merkle_path,
} }
} }
fn has_matching_anchor(&self, anchor: Anchor) -> bool {
if self.note.value() == NoteValue::zero() {
true
} else {
let cm = self.note.commitment();
let path_root = self.merkle_path.root(cm.into());
path_root == anchor
}
}
} }
/// Information about a specific output to receive funds in an [`Action`]. /// Information about a specific output to receive funds in an [`Action`].
@ -324,6 +340,11 @@ impl ActionInfo {
} }
} }
/// Type alias for an in-progress bundle that has no proofs or signatures.
///
/// This is returned by [`Builder::build`].
pub type UnauthorizedBundle<V> = Bundle<InProgress<Unproven, Unauthorized>, V>;
/// A builder that constructs a [`Bundle`] from a set of notes to be spent, and outputs /// A builder that constructs a [`Bundle`] from a set of notes to be spent, and outputs
/// to receive funds. /// to receive funds.
#[derive(Debug)] #[derive(Debug)]
@ -366,15 +387,14 @@ impl Builder {
return Err(SpendError::SpendsDisabled); return Err(SpendError::SpendsDisabled);
} }
let spend = SpendInfo::new(fvk, note, merkle_path).ok_or(SpendError::FvkMismatch)?;
// Consistency check: all anchors must be equal. // Consistency check: all anchors must be equal.
let cm = note.commitment(); if !spend.has_matching_anchor(anchor) {
let path_root = merkle_path.root(cm.into());
if path_root != anchor {
return Err(SpendError::AnchorMismatch); return Err(SpendError::AnchorMismatch);
} }
self.spends self.spends.push(spend);
.push(SpendInfo::new(fvk, note, merkle_path).ok_or(SpendError::FvkMismatch)?);
Ok(()) Ok(())
} }
@ -442,7 +462,7 @@ impl Builder {
pub fn build<V: TryFrom<i64>>( pub fn build<V: TryFrom<i64>>(
self, self,
rng: impl RngCore, rng: impl RngCore,
) -> Result<Option<Bundle<InProgress<Unproven, Unauthorized>, V>>, BuildError> { ) -> Result<Option<UnauthorizedBundle<V>>, BuildError> {
bundle(rng, self.spends, self.outputs, self.bundle_type) bundle(rng, self.spends, self.outputs, self.bundle_type)
} }
} }
@ -456,7 +476,7 @@ pub fn bundle<V: TryFrom<i64>>(
mut spends: Vec<SpendInfo>, mut spends: Vec<SpendInfo>,
mut outputs: Vec<OutputInfo>, mut outputs: Vec<OutputInfo>,
bundle_type: BundleType, bundle_type: BundleType,
) -> Result<Option<Bundle<InProgress<Unproven, Unauthorized>, V>>, BuildError> { ) -> Result<Option<UnauthorizedBundle<V>>, BuildError> {
let (flags, anchor) = bundle_type.bundle_config(); let (flags, anchor) = bundle_type.bundle_config();
let num_requested_spends = spends.len(); let num_requested_spends = spends.len();
@ -465,12 +485,8 @@ pub fn bundle<V: TryFrom<i64>>(
} }
for spend in &spends { for spend in &spends {
if spend.note.value() != NoteValue::zero() { if !spend.has_matching_anchor(anchor) {
let cm = spend.note.commitment(); return Err(BuildError::AnchorMismatch);
let path_root = spend.merkle_path.root(cm.into());
if path_root != anchor {
return Err(BuildError::AnchorMismatch);
}
} }
} }