From 5285737bf085e7387397d7b1f11bbf13cb332a9b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 18:54:00 +0000 Subject: [PATCH 1/9] 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 0000000000..a0261cb475 --- /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 0000000000..e188426863 --- /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 227a3705b0..824f5b0c10 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 { +} From d65968ed38bad266c49e7bb939f3b42578ef5da7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 20:09:09 +0000 Subject: [PATCH 2/9] Skeleton for notes and values --- src/lib.rs | 5 +++++ src/note.rs | 34 ++++++++++++++++++++++++++++++++++ src/value.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/note.rs create mode 100644 src/value.rs diff --git a/src/lib.rs b/src/lib.rs index 824f5b0c10..e993a1c538 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,12 +9,17 @@ mod address; pub mod keys; +mod note; +pub mod value; pub use address::Address; +pub use note::{EncryptedNote, Note, NoteCommitment, Nullifier}; /// 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 { + /// Constraints on values within this chain. + type Value: value::Constraint; } diff --git a/src/note.rs b/src/note.rs new file mode 100644 index 0000000000..22c0840631 --- /dev/null +++ b/src/note.rs @@ -0,0 +1,34 @@ +use crate::{keys::FullViewingKey, value::NoteValue, Address, Chain}; + +/// A discrete amount of funds received by an address. +#[derive(Debug)] +pub struct Note { + /// The recipient of the funds. + recipient: Address, + /// The value of this note. + value: NoteValue, +} + +impl Note { + /// Derives the commitment to this note. + pub fn commitment(&self) -> NoteCommitment { + todo!() + } + + /// Derives the nullifier for this note. + pub fn nullifier(&self, _: &FullViewingKey) -> Nullifier { + todo!() + } +} + +/// An encrypted note. +#[derive(Debug)] +pub struct EncryptedNote; + +/// A commitment to a note. +#[derive(Debug)] +pub struct NoteCommitment; + +/// A unique nullifier for a note. +#[derive(Debug)] +pub struct Nullifier; diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000000..b117c2f98e --- /dev/null +++ b/src/value.rs @@ -0,0 +1,32 @@ +//! Monetary values within the Orchard shielded pool. +//! +//! Values are represented in two places within Orchard: +//! - The value of an individual note, which is unsigned. +//! - The sum of note values within an Orchard [`Action`] or [`Bundle`], which is signed. +//! +//! We give these separate types within this crate. Users should map these types to their +//! own general "amount" type as appropriate. +//! +//! Inside the circuit, values are constrained to be 63-bit integers. +//! - TODO: Should this be constrained further to 53 bits? To Zcash's MAX_MONEY? +//! +//! [`Action`]: crate::bundle::Action +//! [`Bundle`]: crate::bundle::Bundle + +use std::fmt; +use std::marker::PhantomData; + +/// The constraints applied to Orchard values. +pub trait Constraint: fmt::Debug {} + +/// The value of an individual Orchard note. +#[derive(Debug)] +pub struct NoteValue(u64, PhantomData); + +/// A sum of Orchard note values. +#[derive(Debug)] +pub struct ValueSum(i64, PhantomData); + +/// A commitment to a [`ValueSum`]. +#[derive(Debug)] +pub struct ValueCommitment; From 1b9f6450cbbae83296f8b44f0c69f534de832110 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 20:30:35 +0000 Subject: [PATCH 3/9] Add skeleton for actions and bundles --- src/bundle.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/circuit.rs | 2 ++ src/lib.rs | 3 ++ src/tree.rs | 3 ++ 4 files changed, 97 insertions(+) create mode 100644 src/bundle.rs create mode 100644 src/circuit.rs create mode 100644 src/tree.rs diff --git a/src/bundle.rs b/src/bundle.rs new file mode 100644 index 0000000000..631debb573 --- /dev/null +++ b/src/bundle.rs @@ -0,0 +1,89 @@ +//! Structs related to bundles of Orchard actions. + +use std::marker::PhantomData; + +use crate::{ + circuit::Proof, + note::{EncryptedNote, NoteCommitment, Nullifier}, + tree::Anchor, + value::{ValueCommitment, ValueSum}, + Chain, +}; + +/// An action applied to the global ledger. +/// +/// Externally, this both creates a note (adding a commitment to the global ledger), +/// and consumes some note created prior to this action (adding a nullifier to the +/// global ledger). +/// +/// Internally, this may both consume a note and create a note, or it may do only one of +/// the two. TODO: Determine which is more efficient (circuit size vs bundle size). +#[derive(Debug)] +pub struct Action { + /// The nullifier of the note being spent. + nf_old: Nullifier, + /// The randomized verification key for the note being spent. + rk: (), + /// A commitment to the new note being created. + cm_new: NoteCommitment, + /// The encrypted output note. + encrypted_note: EncryptedNote, + /// A commitment to the net value created or consumed by this action. + cv_net: ValueCommitment, +} + +/// A bundle of actions to be applied to the ledger. +/// +/// TODO: Will this ever exist independently of its signatures, outside of a builder? +#[derive(Debug)] +pub struct Bundle { + anchor: Anchor, + actions: Vec, + value_balance: ValueSum, + proof: Proof, + _chain: PhantomData, +} + +impl Bundle { + /// Computes a commitment to the effects of this bundle, suitable for inclusion within + /// a transaction ID. + pub fn commitment(&self) -> BundleCommitment { + todo!() + } +} + +/// An authorized bundle of actions, ready to be committed to the ledger. +#[derive(Debug)] +pub struct SignedBundle { + bundle: Bundle, + action_signatures: Vec<()>, + binding_signature: (), +} + +impl SignedBundle { + /// Computes a commitment to the effects of this bundle, suitable for inclusion within + /// a transaction ID. + /// + /// This is equivalent to [`Bundle::commitment`]. + pub fn commitment(&self) -> BundleCommitment { + self.bundle.commitment() + } + + /// Computes a commitment to the authorizing data within for this bundle. + /// + /// This together with `SignedBundle::commitment` bind the entire bundle. + pub fn authorizing_commitment(&self) -> BundleAuthorizingCommitment { + todo!() + } +} + +/// A commitment to a bundle of actions. +/// +/// This commitment is non-malleable, in the sense that a bundle's commitment will only +/// change if the effects of the bundle are altered. +#[derive(Debug)] +pub struct BundleCommitment; + +/// A commitment to the authorizing data within a bundle of actions. +#[derive(Debug)] +pub struct BundleAuthorizingCommitment; diff --git a/src/circuit.rs b/src/circuit.rs new file mode 100644 index 0000000000..5149a13324 --- /dev/null +++ b/src/circuit.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct Proof(Vec); diff --git a/src/lib.rs b/src/lib.rs index e993a1c538..6f2393cdf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,11 @@ #![deny(unsafe_code)] mod address; +pub mod bundle; +mod circuit; pub mod keys; mod note; +mod tree; pub mod value; pub use address::Address; diff --git a/src/tree.rs b/src/tree.rs new file mode 100644 index 0000000000..e6157326ba --- /dev/null +++ b/src/tree.rs @@ -0,0 +1,3 @@ +/// The root of an Orchard commitment tree. +#[derive(Debug)] +pub struct Anchor; From ae252f57a8bb232c0c641254f4026861f2f72084 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 20:35:54 +0000 Subject: [PATCH 4/9] Add skeleton for RedPallas --- src/bundle.rs | 7 +++--- src/lib.rs | 1 + src/primitives.rs | 7 ++++++ src/primitives/redpallas.rs | 45 +++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/primitives.rs create mode 100644 src/primitives/redpallas.rs diff --git a/src/bundle.rs b/src/bundle.rs index 631debb573..09c78c8dd8 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -5,6 +5,7 @@ use std::marker::PhantomData; use crate::{ circuit::Proof, note::{EncryptedNote, NoteCommitment, Nullifier}, + primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, value::{ValueCommitment, ValueSum}, Chain, @@ -23,7 +24,7 @@ pub struct Action { /// The nullifier of the note being spent. nf_old: Nullifier, /// The randomized verification key for the note being spent. - rk: (), + rk: redpallas::VerificationKey, /// A commitment to the new note being created. cm_new: NoteCommitment, /// The encrypted output note. @@ -56,8 +57,8 @@ impl Bundle { #[derive(Debug)] pub struct SignedBundle { bundle: Bundle, - action_signatures: Vec<()>, - binding_signature: (), + action_signatures: Vec>, + binding_signature: redpallas::Signature, } impl SignedBundle { diff --git a/src/lib.rs b/src/lib.rs index 6f2393cdf7..326ad1e892 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub mod bundle; mod circuit; pub mod keys; mod note; +pub mod primitives; mod tree; pub mod value; diff --git a/src/primitives.rs b/src/primitives.rs new file mode 100644 index 0000000000..42a01fe484 --- /dev/null +++ b/src/primitives.rs @@ -0,0 +1,7 @@ +//! Primitives used in the Orchard protocol. +// TODO: +// - DH stuff +// - EphemeralPublicKey +// - EphemeralSecretKey + +pub mod redpallas; diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs new file mode 100644 index 0000000000..d24fe58df4 --- /dev/null +++ b/src/primitives/redpallas.rs @@ -0,0 +1,45 @@ +//! TODO + +use std::fmt; +use std::marker::PhantomData; + +/// A RedPallas signature type. +pub trait SigType: private::Sealed + fmt::Debug {} + +/// A type variable corresponding to an Orchard spend authorization signature. +#[derive(Debug)] +pub enum SpendAuth {} +impl SigType for SpendAuth {} + +/// A type variable corresponding to an Orchard binding signature. +#[derive(Debug)] +pub enum Binding {} +impl SigType for Binding {} + +/// A RedPallas signing key. +#[derive(Debug)] +pub struct SigningKey { + _t: PhantomData, +} + +/// A RedPallas verification key. +#[derive(Debug)] +pub struct VerificationKey { + _t: PhantomData, +} + +/// A RedPallas signature. +#[derive(Debug)] +pub struct Signature { + _t: PhantomData, +} + +pub(crate) mod private { + use super::{Binding, SpendAuth}; + + pub trait Sealed {} + + impl Sealed for SpendAuth {} + + impl Sealed for Binding {} +} From a564ba76ce5b3623c6050c2cd3b62c8465643849 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 21 Jan 2021 12:16:50 +0000 Subject: [PATCH 5/9] Remove Chain and value::Constraint traits There was push-back on having this crate require these traits, due to the additional complexity within this crate. My rationale for including them was to make it simpler to reason about what is responsible for enforcing chain-specific constraints, and to reduce duplication (by enabling the wrapping chain implementation to use type definitions and leverage all built-in behaviour, instead of newtypes and needing to add a bunch of wrapping logic and boilerplate, some of which would encode chain-specific logic). We'll try working within the requirement that this crate enforces minimal base constraints and hard-codes any constants, and then have the wrapping chain provide encoding prefixes and additional value constraints where necessary. --- src/address.rs | 7 +++--- src/bundle.rs | 16 +++++------- src/keys.rs | 67 +++++++++++++++++++++----------------------------- src/lib.rs | 9 ------- src/note.rs | 12 ++++----- src/value.rs | 10 ++------ 6 files changed, 45 insertions(+), 76 deletions(-) diff --git a/src/address.rs b/src/address.rs index a0261cb475..63646573f9 100644 --- a/src/address.rs +++ b/src/address.rs @@ -1,9 +1,8 @@ -use crate::{keys::Diversifier, Chain}; +use crate::keys::Diversifier; /// A shielded payment address. #[derive(Debug)] -pub struct Address { - chain: C, - d: Diversifier, +pub struct Address { + d: Diversifier, pk_d: (), } diff --git a/src/bundle.rs b/src/bundle.rs index 09c78c8dd8..912f0104ed 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -1,14 +1,11 @@ //! Structs related to bundles of Orchard actions. -use std::marker::PhantomData; - use crate::{ circuit::Proof, note::{EncryptedNote, NoteCommitment, Nullifier}, primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, value::{ValueCommitment, ValueSum}, - Chain, }; /// An action applied to the global ledger. @@ -37,15 +34,14 @@ pub struct Action { /// /// TODO: Will this ever exist independently of its signatures, outside of a builder? #[derive(Debug)] -pub struct Bundle { +pub struct Bundle { anchor: Anchor, actions: Vec, - value_balance: ValueSum, + value_balance: ValueSum, proof: Proof, - _chain: PhantomData, } -impl Bundle { +impl Bundle { /// Computes a commitment to the effects of this bundle, suitable for inclusion within /// a transaction ID. pub fn commitment(&self) -> BundleCommitment { @@ -55,13 +51,13 @@ impl Bundle { /// An authorized bundle of actions, ready to be committed to the ledger. #[derive(Debug)] -pub struct SignedBundle { - bundle: Bundle, +pub struct SignedBundle { + bundle: Bundle, action_signatures: Vec>, binding_signature: redpallas::Signature, } -impl SignedBundle { +impl SignedBundle { /// Computes a commitment to the effects of this bundle, suitable for inclusion within /// a transaction ID. /// diff --git a/src/keys.rs b/src/keys.rs index e188426863..fcf32195c8 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,17 +1,6 @@ //! 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}; +use crate::address::Address; /// A spending key, from which all key material is derived. /// @@ -20,32 +9,32 @@ use crate::{address::Address, Chain}; /// 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); +pub struct SpendingKey; #[derive(Debug)] -pub(crate) struct SpendAuthorizingKey(PhantomData); +pub(crate) struct SpendAuthorizingKey; -impl From<&SpendingKey> for SpendAuthorizingKey { - fn from(_: &SpendingKey) -> Self { +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); +pub(crate) struct AuthorizingKey; -impl From<&SpendAuthorizingKey> for AuthorizingKey { - fn from(_: &SpendAuthorizingKey) -> Self { +impl From<&SpendAuthorizingKey> for AuthorizingKey { + fn from(_: &SpendAuthorizingKey) -> Self { todo!() } } #[derive(Debug)] -pub(crate) struct NullifierDerivingKey(PhantomData); +pub(crate) struct NullifierDerivingKey; -impl From<&SpendingKey> for NullifierDerivingKey { - fn from(_: &SpendingKey) -> Self { +impl From<&SpendingKey> for NullifierDerivingKey { + fn from(_: &SpendingKey) -> Self { todo!() } } @@ -53,10 +42,10 @@ impl From<&SpendingKey> for NullifierDerivingKey { /// A key that provides the capability to recover outgoing transaction information from /// the block chain. #[derive(Debug)] -pub struct OutgoingViewingKey(PhantomData); +pub struct OutgoingViewingKey; -impl From<&SpendingKey> for OutgoingViewingKey { - fn from(_: &SpendingKey) -> Self { +impl From<&SpendingKey> for OutgoingViewingKey { + fn from(_: &SpendingKey) -> Self { todo!() } } @@ -71,21 +60,21 @@ impl From<&SpendingKey> for OutgoingViewingKey { /// /// 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, +pub struct FullViewingKey { + ak: AuthorizingKey, + nk: NullifierDerivingKey, + ovk: OutgoingViewingKey, } -impl From<&SpendingKey> for FullViewingKey { - fn from(_: &SpendingKey) -> Self { +impl From<&SpendingKey> for FullViewingKey { + fn from(_: &SpendingKey) -> Self { todo!() } } -impl FullViewingKey { +impl FullViewingKey { /// Returns the payment address for this key corresponding to the given diversifier. - pub fn address(&self, d: Diversifier) -> Address { + pub fn address(&self, d: Diversifier) -> Address { IncomingViewingKey::from(self).address(d) } } @@ -96,7 +85,7 @@ impl FullViewingKey { // This is a newtype around a `u128` for simplicity, and enforces the diversifier size // during all operations. #[derive(Debug)] -pub struct Diversifier(u128, PhantomData); +pub struct Diversifier(u128); /// 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. @@ -107,17 +96,17 @@ pub struct Diversifier(u128, PhantomData); /// 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); +pub struct IncomingViewingKey; -impl From<&FullViewingKey> for IncomingViewingKey { - fn from(_: &FullViewingKey) -> Self { +impl From<&FullViewingKey> for IncomingViewingKey { + fn from(_: &FullViewingKey) -> Self { todo!() } } -impl IncomingViewingKey { +impl IncomingViewingKey { /// Returns the payment address for this key corresponding to the given diversifier. - pub fn address(&self, _: Diversifier) -> Address { + pub fn address(&self, _: Diversifier) -> Address { todo!() } } diff --git a/src/lib.rs b/src/lib.rs index 326ad1e892..737a65a5fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,12 +18,3 @@ pub mod value; pub use address::Address; pub use note::{EncryptedNote, Note, NoteCommitment, Nullifier}; - -/// 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 { - /// Constraints on values within this chain. - type Value: value::Constraint; -} diff --git a/src/note.rs b/src/note.rs index 22c0840631..d35fb4ca8e 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,22 +1,22 @@ -use crate::{keys::FullViewingKey, value::NoteValue, Address, Chain}; +use crate::{keys::FullViewingKey, value::NoteValue, Address}; /// A discrete amount of funds received by an address. #[derive(Debug)] -pub struct Note { +pub struct Note { /// The recipient of the funds. - recipient: Address, + recipient: Address, /// The value of this note. - value: NoteValue, + value: NoteValue, } -impl Note { +impl Note { /// Derives the commitment to this note. pub fn commitment(&self) -> NoteCommitment { todo!() } /// Derives the nullifier for this note. - pub fn nullifier(&self, _: &FullViewingKey) -> Nullifier { + pub fn nullifier(&self, _: &FullViewingKey) -> Nullifier { todo!() } } diff --git a/src/value.rs b/src/value.rs index b117c2f98e..6cf96cdc14 100644 --- a/src/value.rs +++ b/src/value.rs @@ -13,19 +13,13 @@ //! [`Action`]: crate::bundle::Action //! [`Bundle`]: crate::bundle::Bundle -use std::fmt; -use std::marker::PhantomData; - -/// The constraints applied to Orchard values. -pub trait Constraint: fmt::Debug {} - /// The value of an individual Orchard note. #[derive(Debug)] -pub struct NoteValue(u64, PhantomData); +pub struct NoteValue(u64); /// A sum of Orchard note values. #[derive(Debug)] -pub struct ValueSum(i64, PhantomData); +pub struct ValueSum(i64); /// A commitment to a [`ValueSum`]. #[derive(Debug)] From aeddfb64e58635e40c0a6406dc392f0fb3b0be1f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Feb 2021 14:16:58 +0000 Subject: [PATCH 6/9] Make Diversifier a newtype around [u8; 11] --- src/keys.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index fcf32195c8..e7654e64f2 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -81,11 +81,8 @@ impl FullViewingKey { /// 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); +pub struct Diversifier([u8; 11]); /// 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. From 1add6a7ef0a27165f6564bbda952461794248385 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 3 Feb 2021 14:19:29 +0000 Subject: [PATCH 7/9] Fix FVK doc comment --- src/keys.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index e7654e64f2..2ad301f0db 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -52,11 +52,8 @@ impl From<&SpendingKey> for OutgoingViewingKey { /// 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. +/// This key is useful anywhere you need to maintain accurate balance, but do not want the +/// ability to spend funds (such as a view-only wallet). /// /// TODO: Should we just define the FVK to include extended stuff like the diversifier key? #[derive(Debug)] From bf9e77b629aee259143f5c4d74d87ac35cf09f6a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 8 Feb 2021 15:01:34 +0000 Subject: [PATCH 8/9] Move ovk to be derived from fvk instead of the spending key --- src/keys.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index 2ad301f0db..cc2c632672 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -39,17 +39,6 @@ impl From<&SpendingKey> for NullifierDerivingKey { } } -/// A key that provides the capability to recover outgoing transaction information from -/// the block chain. -#[derive(Debug)] -pub struct OutgoingViewingKey; - -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 anywhere you need to maintain accurate balance, but do not want the @@ -60,7 +49,7 @@ impl From<&SpendingKey> for OutgoingViewingKey { pub struct FullViewingKey { ak: AuthorizingKey, nk: NullifierDerivingKey, - ovk: OutgoingViewingKey, + rivk: (), } impl From<&SpendingKey> for FullViewingKey { @@ -87,8 +76,8 @@ pub struct Diversifier([u8; 11]); /// 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. +/// This key is not suitable for use on its own in a wallet, as it cannot maintain +/// accurate balance. You should use a [`FullViewingKey`] instead. #[derive(Debug)] pub struct IncomingViewingKey; @@ -104,3 +93,17 @@ impl IncomingViewingKey { todo!() } } + +/// A key that provides the capability to recover outgoing transaction information from +/// the block chain. +/// +/// This key is not suitable for use on its own in a wallet, as it cannot maintain +/// accurate balance. You should use a [`FullViewingKey`] instead. +#[derive(Debug)] +pub struct OutgoingViewingKey; + +impl From<&FullViewingKey> for OutgoingViewingKey { + fn from(_: &FullViewingKey) -> Self { + todo!() + } +} From 5bce857569008abd2a57056f6ec466efec3443db Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 8 Feb 2021 15:21:04 +0000 Subject: [PATCH 9/9] Fill out note components --- src/note.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/note.rs b/src/note.rs index d35fb4ca8e..dbfa575c10 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,5 +1,23 @@ use crate::{keys::FullViewingKey, value::NoteValue, Address}; +/// The ZIP 212 seed randomness for a note. +#[derive(Debug)] +struct RandomSeed([u8; 32]); + +impl RandomSeed { + fn psi(&self) -> () { + todo!() + } + + fn rcm(&self) -> () { + todo!() + } + + fn esk(&self) -> () { + todo!() + } +} + /// A discrete amount of funds received by an address. #[derive(Debug)] pub struct Note { @@ -7,6 +25,15 @@ pub struct Note { recipient: Address, /// The value of this note. value: NoteValue, + /// A unique creation ID for this note. + /// + /// This is set to the nullifier of the note that was spent in the [`Action`] that + /// created this note. + /// + /// [`Action`]: crate::bundle::Action + rho: Nullifier, + /// The seed randomness for various note components. + rseed: RandomSeed, } impl Note {