Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion benches/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use pprof::criterion::{Output, PProfProfiler};

use orchard::{
builder::{Builder, BundleType},
bundle::Authorization,
circuit::{ProvingKey, VerifyingKey},
keys::{FullViewingKey, Scope, SpendingKey},
note::AssetBase,
Expand Down Expand Up @@ -86,7 +87,13 @@ fn criterion_benchmark<FL: OrchardFlavorBench>(c: &mut Criterion) {
.unwrap();
assert!(bundle.verify_proof(&vk).is_ok());
group.bench_function(BenchmarkId::new("bundle", num_recipients), |b| {
b.iter(|| bundle.authorization().proof().verify(&vk, &instances));
b.iter(|| {
bundle
.authorization()
.proof()
.unwrap()
.verify(&vk, &instances)
});
});
}
}
Expand Down
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
reorder_imports = false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line
(consider updating ide setup to be automatic)

70 changes: 33 additions & 37 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use crate::{
},
note::{AssetBase, Note, Rho, TransmittedNoteCiphertext},
orchard_flavor::{Flavor, OrchardFlavor, OrchardVanilla, OrchardZSA},
primitives::redpallas::{self, Binding, SpendAuth},
swap_bundle::{ActionGroup, ActionGroupAuthorized},
primitives::redpallas::{self, Binding, SpendAuth, SigningKey},
swap_bundle::ActionGroupAuthorized,
tree::{Anchor, MerklePath},
value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum},
};
Expand Down Expand Up @@ -65,10 +65,16 @@ impl BundleType {
bundle_required: false,
};

/// The default bundle with all flags enabled, including Asset Swaps.
pub const DEFAULT_SWAP: BundleType = BundleType::Transactional {
flags: Flags::ENABLED_WITH_SWAPS,
bundle_required: false,
};

/// The DISABLED bundle type does not permit any bundle to be produced, and when used in the
/// builder will prevent any spends or outputs from being added.
pub const DISABLED: BundleType = BundleType::Transactional {
flags: Flags::from_parts(false, false, false),
flags: Flags::from_parts(false, false, false, false),
bundle_required: false,
};

Expand Down Expand Up @@ -513,12 +519,6 @@ impl BundleMetadata {
/// A tuple containing an in-progress bundle with no proofs or signatures, and its associated metadata.
pub type UnauthorizedBundleWithMetadata<V, FL> = (UnauthorizedBundle<V, FL>, BundleMetadata);

/// A tuple containing an in-progress action group with no proofs or signatures, and its associated metadata.
pub type UnauthorizedActionGroupWithMetadata<V> = (
ActionGroup<InProgress<Unproven, Unauthorized>, V>,
BundleMetadata,
);

/// A builder that constructs a [`Bundle`] from a set of notes to be spent, and outputs
/// to receive funds.
#[derive(Debug)]
Expand All @@ -544,6 +544,14 @@ impl Builder {
}
}

/// Returns true if the builder is empty.
pub fn is_empty(&self) -> bool {
self.spends.is_empty()
&& self.outputs.is_empty()
&& self.burn.is_empty()
&& self.reference_notes.is_empty()
}

/// Adds a note to be spent in this transaction.
///
/// - `note` is a spendable note, obtained by trial-decrypting an [`Action`] using the
Expand Down Expand Up @@ -690,6 +698,7 @@ impl Builder {
self.bundle_type,
self.spends,
self.outputs,
0,
SpecificBuilderParams::BundleParams(self.burn),
)
}
Expand All @@ -701,8 +710,8 @@ impl Builder {
pub fn build_action_group<V: TryFrom<i64>>(
self,
rng: impl RngCore,
timelimit: u32,
) -> Result<UnauthorizedActionGroupWithMetadata<V>, BuildError> {
expiry_height: u32,
) -> Result<UnauthorizedBundleWithMetadata<V, OrchardZSA>, BuildError> {
if !self.burn.is_empty() {
return Err(BuildError::BurnNotEmptyInActionGroup);
}
Expand All @@ -712,14 +721,9 @@ impl Builder {
self.bundle_type,
self.spends,
self.outputs,
expiry_height,
SpecificBuilderParams::ActionGroupParams(self.reference_notes),
)
.map(|(action_group, metadata)| {
(
ActionGroup::from_parts(action_group, timelimit, None),
metadata,
)
})
}
}

Expand Down Expand Up @@ -813,6 +817,7 @@ pub fn bundle<V: TryFrom<i64>, FL: OrchardFlavor>(
bundle_type: BundleType,
spends: Vec<SpendInfo>,
outputs: Vec<OutputInfo>,
expiry_height: u32,
specific_params: SpecificBuilderParams,
) -> Result<UnauthorizedBundleWithMetadata<V, FL>, BuildError> {
let flags = bundle_type.flags();
Expand Down Expand Up @@ -979,6 +984,7 @@ pub fn bundle<V: TryFrom<i64>, FL: OrchardFlavor>(
result_value_balance,
burn,
anchor,
expiry_height,
InProgress {
proof: Unproven {
witnesses,
Expand Down Expand Up @@ -1019,6 +1025,10 @@ impl<P, S: InProgressSignatures> InProgress<P, S> {

impl<P: fmt::Debug, S: InProgressSignatures> Authorization for InProgress<P, S> {
type SpendAuth = S::SpendAuth;

fn proof(&self) -> Option<&Proof> {
None
}
}

/// Marker for a bundle without a proof.
Expand Down Expand Up @@ -1119,8 +1129,8 @@ pub struct SigningMetadata {
/// If this action is spending a dummy note, this field holds that note's spend
/// authorizing key.
///
/// These keys are used automatically in [`Bundle<Unauthorized>::prepare`] or
/// [`Bundle<Unauthorized>::apply_signatures`] to sign dummy spends.
/// These keys are used automatically in [`Bundle<Unauthorized, _, _>::prepare`] or
/// [`Bundle<Unauthorized, _, _>::apply_signatures`] to sign dummy spends.
dummy_ask: Option<SpendAuthorizingKey>,
parts: SigningParts,
}
Expand Down Expand Up @@ -1256,23 +1266,15 @@ impl<V, D: OrchardDomainCommon> Bundle<InProgress<Proof, Unauthorized>, V, D> {
})
.finalize()
}
}

impl<V, D: OrchardDomainCommon> Bundle<InProgress<Proof, Unauthorized>, V, D> {
/// Applies signatures to this action group, in order to authorize it.
/// Applies signatures to this bundle as an action group, in order to authorize it.
#[allow(clippy::type_complexity)]
pub fn apply_signatures_for_action_group<R: RngCore + CryptoRng>(
self,
mut rng: R,
action_group_digest: [u8; 32],
signing_keys: &[SpendAuthorizingKey],
) -> Result<
(
redpallas::SigningKey<Binding>,
Bundle<ActionGroupAuthorized, V, D>,
),
BuildError,
> {
) -> Result<(Bundle<ActionGroupAuthorized, V, D>, SigningKey<Binding>), BuildError> {
signing_keys
.iter()
.fold(
Expand Down Expand Up @@ -1395,20 +1397,14 @@ impl<V, D: OrchardDomainCommon> Bundle<InProgress<Proof, ActionGroupPartiallyAut
#[allow(clippy::type_complexity)]
pub fn finalize(
self,
) -> Result<
(
redpallas::SigningKey<Binding>,
Bundle<ActionGroupAuthorized, V, D>,
),
BuildError,
> {
) -> Result<(Bundle<ActionGroupAuthorized, V, D>, SigningKey<Binding>), BuildError> {
let bsk = self.authorization().sigs.bsk;
self.try_map_authorization(
&mut (),
|_, _, maybe| maybe.finalize(),
|_, partial| Ok(ActionGroupAuthorized::from_parts(partial.proof)),
)
.map(|bundle| (bsk, bundle))
.map(|bundle| (bundle, bsk))
}
}

Expand Down
Loading