Extract InProgress type from Unauthorized and PartiallyAuthorized

This enables bundle proofs and signatures to be handled separately
outside the builder.
This commit is contained in:
Jack Grigg 2021-07-28 13:45:24 +01:00
parent 078b71a960
commit 6b495f711a
1 changed files with 42 additions and 16 deletions

View File

@ -285,7 +285,7 @@ impl Builder {
mut self, mut self,
mut rng: impl RngCore, mut rng: impl RngCore,
pk: &ProvingKey, pk: &ProvingKey,
) -> Result<Bundle<Unauthorized, V>, Error> { ) -> Result<Bundle<InProgress<Proof, Unauthorized>, V>, Error> {
// Pair up the spends and recipients, extending with dummy values as necessary. // Pair up the spends and recipients, extending with dummy values as necessary.
// //
// TODO: Do we want to shuffle the order like we do for Sapling? And if we do, do // TODO: Do we want to shuffle the order like we do for Sapling? And if we do, do
@ -360,11 +360,31 @@ impl Builder {
flags, flags,
result_value_balance, result_value_balance,
anchor, anchor,
Unauthorized { proof, bsk }, InProgress {
proof,
sigs: Unauthorized { bsk },
},
)) ))
} }
} }
/// Marker trait representing bundle signatures in the process of being created.
pub trait InProgressSignatures {
/// The authorization type of an Orchard action in the process of being authorized.
type SpendAuth;
}
/// Marker for a bundle in the process of being built.
#[derive(Debug)]
pub struct InProgress<P, S: InProgressSignatures> {
proof: P,
sigs: S,
}
impl<P, S: InProgressSignatures> Authorization for InProgress<P, S> {
type SpendAuth = S::SpendAuth;
}
/// The parts needed to sign an [`Action`]. /// The parts needed to sign an [`Action`].
#[derive(Debug)] #[derive(Debug)]
pub struct SigningParts { pub struct SigningParts {
@ -375,14 +395,13 @@ pub struct SigningParts {
alpha: pallas::Scalar, alpha: pallas::Scalar,
} }
/// Marker for an unauthorized bundle, with a proof but no signatures. /// Marker for an unauthorized bundle with no signatures.
#[derive(Debug)] #[derive(Debug)]
pub struct Unauthorized { pub struct Unauthorized {
proof: Proof,
bsk: redpallas::SigningKey<Binding>, bsk: redpallas::SigningKey<Binding>,
} }
impl Authorization for Unauthorized { impl InProgressSignatures for Unauthorized {
type SpendAuth = SigningMetadata; type SpendAuth = SigningMetadata;
} }
@ -401,12 +420,11 @@ pub struct SigningMetadata {
/// Marker for a partially-authorized bundle, in the process of being signed. /// Marker for a partially-authorized bundle, in the process of being signed.
#[derive(Debug)] #[derive(Debug)]
pub struct PartiallyAuthorized { pub struct PartiallyAuthorized {
proof: Proof,
binding_signature: redpallas::Signature<Binding>, binding_signature: redpallas::Signature<Binding>,
sighash: [u8; 32], sighash: [u8; 32],
} }
impl Authorization for PartiallyAuthorized { impl InProgressSignatures for PartiallyAuthorized {
type SpendAuth = MaybeSigned; type SpendAuth = MaybeSigned;
} }
@ -430,7 +448,7 @@ impl MaybeSigned {
} }
} }
impl<V> Bundle<Unauthorized, V> { impl<P, V> Bundle<InProgress<P, Unauthorized>, V> {
/// Loads the sighash into this bundle, preparing it for signing. /// Loads the sighash into this bundle, preparing it for signing.
/// ///
/// This API ensures that all signatures are created over the same sighash. /// This API ensures that all signatures are created over the same sighash.
@ -438,7 +456,7 @@ impl<V> Bundle<Unauthorized, V> {
self, self,
mut rng: R, mut rng: R,
sighash: [u8; 32], sighash: [u8; 32],
) -> Bundle<PartiallyAuthorized, V> { ) -> Bundle<InProgress<P, PartiallyAuthorized>, V> {
self.authorize( self.authorize(
&mut rng, &mut rng,
|rng, _, SigningMetadata { dummy_ask, parts }| { |rng, _, SigningMetadata { dummy_ask, parts }| {
@ -448,14 +466,18 @@ impl<V> Bundle<Unauthorized, V> {
.map(MaybeSigned::Signature) .map(MaybeSigned::Signature)
.unwrap_or(MaybeSigned::SigningMetadata(parts)) .unwrap_or(MaybeSigned::SigningMetadata(parts))
}, },
|rng, unauth| PartiallyAuthorized { |rng, auth| InProgress {
proof: unauth.proof, proof: auth.proof,
binding_signature: unauth.bsk.sign(rng, &sighash), sigs: PartiallyAuthorized {
binding_signature: auth.sigs.bsk.sign(rng, &sighash),
sighash, sighash,
}, },
},
) )
} }
}
impl<V> Bundle<InProgress<Proof, Unauthorized>, V> {
/// Applies signatures to this bundle, in order to authorize it. /// Applies signatures to this bundle, in order to authorize it.
pub fn apply_signatures<R: RngCore + CryptoRng>( pub fn apply_signatures<R: RngCore + CryptoRng>(
self, self,
@ -472,7 +494,7 @@ impl<V> Bundle<Unauthorized, V> {
} }
} }
impl<V> Bundle<PartiallyAuthorized, V> { impl<P, V> Bundle<InProgress<P, PartiallyAuthorized>, V> {
/// Signs this bundle with the given [`SpendAuthorizingKey`]. /// Signs this bundle with the given [`SpendAuthorizingKey`].
/// ///
/// This will apply signatures for all notes controlled by this spending key. /// This will apply signatures for all notes controlled by this spending key.
@ -482,14 +504,18 @@ impl<V> Bundle<PartiallyAuthorized, V> {
&mut rng, &mut rng,
|rng, partial, maybe| match maybe { |rng, partial, maybe| match maybe {
MaybeSigned::SigningMetadata(parts) if parts.ak == expected_ak => { MaybeSigned::SigningMetadata(parts) if parts.ak == expected_ak => {
MaybeSigned::Signature(ask.randomize(&parts.alpha).sign(rng, &partial.sighash)) MaybeSigned::Signature(
ask.randomize(&parts.alpha).sign(rng, &partial.sigs.sighash),
)
} }
s => s, s => s,
}, },
|_, partial| partial, |_, partial| partial,
) )
} }
}
impl<V> Bundle<InProgress<Proof, PartiallyAuthorized>, V> {
/// Finalizes this bundle, enabling it to be included in a transaction. /// Finalizes this bundle, enabling it to be included in a transaction.
/// ///
/// Returns an error if any signatures are missing. /// Returns an error if any signatures are missing.
@ -500,7 +526,7 @@ impl<V> Bundle<PartiallyAuthorized, V> {
|_, partial| { |_, partial| {
Ok(Authorized::from_parts( Ok(Authorized::from_parts(
partial.proof, partial.proof,
partial.binding_signature, partial.sigs.binding_signature,
)) ))
}, },
) )