From 5285737bf085e7387397d7b1f11bbf13cb332a9b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 18:54:00 +0000 Subject: [PATCH] Add skeleton of key structure --- src/address.rs | 9 ++++ src/keys.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 12 +++++ 3 files changed, 144 insertions(+) create mode 100644 src/address.rs create mode 100644 src/keys.rs diff --git a/src/address.rs b/src/address.rs new file mode 100644 index 00000000..a0261cb4 --- /dev/null +++ b/src/address.rs @@ -0,0 +1,9 @@ +use crate::{keys::Diversifier, Chain}; + +/// A shielded payment address. +#[derive(Debug)] +pub struct Address { + chain: C, + d: Diversifier, + pk_d: (), +} diff --git a/src/keys.rs b/src/keys.rs new file mode 100644 index 00000000..e1884268 --- /dev/null +++ b/src/keys.rs @@ -0,0 +1,123 @@ +//! Key structures for Orchard. +//! +//! TODO: Should we have the concept of a Network here? Or make these standalone without +//! defined string encodings, and use newtypes in Zcash? +//! - The latter might get messy, but would maintain the crate abstraction. +//! - One approach might be to make all these types take a type parameter that provides +//! encoding and decoding support, and then instantiate it in Zcash inside newtypes. +//! - We will need to encode some decisions here (like the size of the diversifier), which +//! depend on the encoding, so another alternative is we just require Bech32 and then +//! have the constrained type provide the HRP. + +use std::marker::PhantomData; + +use crate::{address::Address, Chain}; + +/// A spending key, from which all key material is derived. +/// +/// TODO: In Sapling we never actually used this, instead deriving everything via ZIP 32, +/// so that we could maintain Bitcoin-like HD keys with properties like non-hardened +/// derivation. If we decide that we don't actually require non-hardened derivation, then +/// we could greatly simplify the HD structure and use this struct directly. +#[derive(Debug)] +pub struct SpendingKey(PhantomData); + +#[derive(Debug)] +pub(crate) struct SpendAuthorizingKey(PhantomData); + +impl From<&SpendingKey> for SpendAuthorizingKey { + fn from(_: &SpendingKey) -> Self { + todo!() + } +} + +/// TODO: This is its protocol spec name for Sapling, but I'd prefer a different name. +#[derive(Debug)] +pub(crate) struct AuthorizingKey(PhantomData); + +impl From<&SpendAuthorizingKey> for AuthorizingKey { + fn from(_: &SpendAuthorizingKey) -> Self { + todo!() + } +} + +#[derive(Debug)] +pub(crate) struct NullifierDerivingKey(PhantomData); + +impl From<&SpendingKey> for NullifierDerivingKey { + fn from(_: &SpendingKey) -> Self { + todo!() + } +} + +/// A key that provides the capability to recover outgoing transaction information from +/// the block chain. +#[derive(Debug)] +pub struct OutgoingViewingKey(PhantomData); + +impl From<&SpendingKey> for OutgoingViewingKey { + fn from(_: &SpendingKey) -> Self { + todo!() + } +} + +/// A key that provides the capability to view incoming and outgoing transactions. +/// +/// This key is useful in situations where you only need the capability to detect inbound +/// payments, such as merchant terminals. +/// +/// This key is not suitable for use in a wallet, as it cannot maintain accurate balance. +/// You should use a [`FullViewingKey`] instead. +/// +/// TODO: Should we just define the FVK to include extended stuff like the diversifier key? +#[derive(Debug)] +pub struct FullViewingKey { + ak: AuthorizingKey, + nk: NullifierDerivingKey, + ovk: OutgoingViewingKey, +} + +impl From<&SpendingKey> for FullViewingKey { + fn from(_: &SpendingKey) -> Self { + todo!() + } +} + +impl FullViewingKey { + /// Returns the payment address for this key corresponding to the given diversifier. + pub fn address(&self, d: Diversifier) -> Address { + IncomingViewingKey::from(self).address(d) + } +} + +/// A diversifier that can be used to derive a specific [`Address`] from a +/// [`FullViewingKey`] or [`IncomingViewingKey`]. +// +// This is a newtype around a `u128` for simplicity, and enforces the diversifier size +// during all operations. +#[derive(Debug)] +pub struct Diversifier(u128, PhantomData); + +/// A key that provides the capability to detect and decrypt incoming notes from the block +/// chain, without being able to spend the notes or detect when they are spent. +/// +/// This key is useful in situations where you only need the capability to detect inbound +/// payments, such as merchant terminals. +/// +/// This key is not suitable for use in a wallet, as it cannot maintain accurate balance. +/// You should use a [`FullViewingKey`] instead. +#[derive(Debug)] +pub struct IncomingViewingKey(PhantomData); + +impl From<&FullViewingKey> for IncomingViewingKey { + fn from(_: &FullViewingKey) -> Self { + todo!() + } +} + +impl IncomingViewingKey { + /// Returns the payment address for this key corresponding to the given diversifier. + pub fn address(&self, _: Diversifier) -> Address { + todo!() + } +} diff --git a/src/lib.rs b/src/lib.rs index 227a3705..824f5b0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,3 +6,15 @@ #![deny(missing_debug_implementations)] #![deny(missing_docs)] #![deny(unsafe_code)] + +mod address; +pub mod keys; + +pub use address::Address; + +/// Chain-specific constants and constraints for Orchard. +/// +/// The purpose of this trait is to encapsulate things like the human-readable prefixes +/// for encoded addresses, or the range of allowable values for notes. +pub trait Chain { +}