Add methods to the Sealed trait, simplifying types.
The motivation is as follows. The sealed trait pattern allows creating a type-level equivalent of an enum: the trait corresponds to the enum type and its implementors correspond to the enum variants; the `Sealed` restriction ensures that there is a fixed set of enum variants. In this picture, adding methods to the public trait corresponds to a public method on an enum, while adding methods to the private trait corresponds to a private method on an enum. This means that we can add a method to get the basepoint (whose possible choices are enumerated by SigType) and avoid having to do specialized impls.
This commit is contained in:
parent
b44f149381
commit
84b042003b
22
src/lib.rs
22
src/lib.rs
|
@ -42,9 +42,23 @@ impl SigType for Binding {}
|
|||
pub struct SpendAuth {}
|
||||
impl SigType for SpendAuth {}
|
||||
|
||||
mod private {
|
||||
pub(crate) mod private {
|
||||
use super::*;
|
||||
pub trait Sealed {}
|
||||
impl Sealed for Binding {}
|
||||
impl Sealed for SpendAuth {}
|
||||
pub trait Sealed {
|
||||
fn basepoint() -> jubjub::ExtendedPoint;
|
||||
}
|
||||
impl Sealed for Binding {
|
||||
fn basepoint() -> jubjub::ExtendedPoint {
|
||||
jubjub::AffinePoint::from_bytes(constants::BINDINGSIG_BASEPOINT_BYTES)
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
impl Sealed for SpendAuth {
|
||||
fn basepoint() -> jubjub::ExtendedPoint {
|
||||
jubjub::AffinePoint::from_bytes(constants::SPENDAUTHSIG_BASEPOINT_BYTES)
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
|
||||
use crate::{Binding, Error, Randomizer, SigType, Signature, SpendAuth};
|
||||
use crate::{Binding, Error, Randomizer, Scalar, SigType, Signature, SpendAuth};
|
||||
|
||||
/// A refinement type for `[u8; 32]` indicating that the bytes represent
|
||||
/// an encoding of a RedJubJub public key.
|
||||
|
@ -62,6 +62,15 @@ impl<T: SigType> TryFrom<PublicKeyBytes<T>> for PublicKey<T> {
|
|||
}
|
||||
|
||||
impl<T: SigType> PublicKey<T> {
|
||||
pub(crate) fn from_secret(s: &Scalar) -> PublicKey<T> {
|
||||
let point = &T::basepoint() * s;
|
||||
let bytes = PublicKeyBytes {
|
||||
bytes: jubjub::AffinePoint::from(&point).to_bytes(),
|
||||
_marker: PhantomData,
|
||||
};
|
||||
PublicKey { bytes, point }
|
||||
}
|
||||
|
||||
/// Randomize this public key with the given `randomizer`.
|
||||
pub fn randomize(&self, randomizer: Randomizer) -> PublicKey<T> {
|
||||
unimplemented!();
|
||||
|
|
|
@ -10,7 +10,7 @@ use rand_core::{CryptoRng, RngCore};
|
|||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SecretKey<T: SigType> {
|
||||
sk: Scalar,
|
||||
_marker: PhantomData<T>,
|
||||
pk: PublicKey<T>,
|
||||
}
|
||||
|
||||
impl<T: SigType> From<SecretKey<T>> for [u8; 32] {
|
||||
|
@ -19,21 +19,17 @@ impl<T: SigType> From<SecretKey<T>> for [u8; 32] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: SigType> TryFrom<[u8; 32]> for SecretKey<T> {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
|
||||
// XXX-jubjub: it does not make sense for this to be a CtOption...
|
||||
// XXX-jubjub: this takes a borrow but point deser doesn't
|
||||
let maybe_sk = Scalar::from_bytes(&bytes);
|
||||
if maybe_sk.is_some().into() {
|
||||
Ok(SecretKey {
|
||||
sk: maybe_sk.unwrap(),
|
||||
_marker: PhantomData,
|
||||
})
|
||||
} else {
|
||||
Err(Error::MalformedSecretKey)
|
||||
}
|
||||
impl<T: SigType> From<[u8; 32]> for SecretKey<T> {
|
||||
fn from(bytes: [u8; 32]) -> Self {
|
||||
let sk = {
|
||||
// XXX-jubjub: would be nice to unconditionally deser
|
||||
// This incantation ensures deserialization is infallible.
|
||||
let mut wide = [0; 64];
|
||||
wide[0..32].copy_from_slice(&bytes);
|
||||
Scalar::from_bytes_wide(&wide)
|
||||
};
|
||||
let pk = PublicKey::from_secret(&sk);
|
||||
SecretKey { sk, pk }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,40 +50,6 @@ where
|
|||
}
|
||||
*/
|
||||
|
||||
impl<'a> From<&'a SecretKey<SpendAuth>> for PublicKey<SpendAuth> {
|
||||
fn from(sk: &'a SecretKey<SpendAuth>) -> PublicKey<SpendAuth> {
|
||||
// XXX-jubjub: this is pretty baroque
|
||||
// XXX-jubjub: provide basepoint tables for generators
|
||||
let basepoint: jubjub::ExtendedPoint =
|
||||
jubjub::AffinePoint::from_bytes(crate::constants::SPENDAUTHSIG_BASEPOINT_BYTES)
|
||||
.unwrap()
|
||||
.into();
|
||||
pk_from_sk_inner(sk, basepoint)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a SecretKey<Binding>> for PublicKey<Binding> {
|
||||
fn from(sk: &'a SecretKey<Binding>) -> PublicKey<Binding> {
|
||||
let basepoint: jubjub::ExtendedPoint =
|
||||
jubjub::AffinePoint::from_bytes(crate::constants::BINDINGSIG_BASEPOINT_BYTES)
|
||||
.unwrap()
|
||||
.into();
|
||||
pk_from_sk_inner(sk, basepoint)
|
||||
}
|
||||
}
|
||||
|
||||
fn pk_from_sk_inner<T: SigType>(
|
||||
sk: &SecretKey<T>,
|
||||
basepoint: jubjub::ExtendedPoint,
|
||||
) -> PublicKey<T> {
|
||||
let point = &basepoint * &sk.sk;
|
||||
let bytes = PublicKeyBytes {
|
||||
bytes: jubjub::AffinePoint::from(&point).to_bytes(),
|
||||
_marker: PhantomData,
|
||||
};
|
||||
PublicKey { bytes, point }
|
||||
}
|
||||
|
||||
impl<T: SigType> SecretKey<T> {
|
||||
/// Randomize this public key with the given `randomizer`.
|
||||
pub fn randomize(&self, randomizer: Randomizer) -> PublicKey<T> {
|
||||
|
|
Loading…
Reference in New Issue