Skip to content

Commit

Permalink
Merge pull request #2 from zcash/crate-skeleton
Browse files Browse the repository at this point in the history
Crate skeleton
  • Loading branch information
ebfull authored Feb 9, 2021
2 parents 6c14880 + 5bce857 commit 744b39d
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::keys::Diversifier;

/// A shielded payment address.
#[derive(Debug)]
pub struct Address {
d: Diversifier,
pk_d: (),
}
86 changes: 86 additions & 0 deletions src/bundle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! Structs related to bundles of Orchard actions.

use crate::{
circuit::Proof,
note::{EncryptedNote, NoteCommitment, Nullifier},
primitives::redpallas::{self, Binding, SpendAuth},
tree::Anchor,
value::{ValueCommitment, ValueSum},
};

/// 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: redpallas::VerificationKey<SpendAuth>,
/// 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<Action>,
value_balance: ValueSum,
proof: Proof,
}

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<redpallas::Signature<SpendAuth>>,
binding_signature: redpallas::Signature<Binding>,
}

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;
2 changes: 2 additions & 0 deletions src/circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[derive(Debug)]
pub struct Proof(Vec<u8>);
109 changes: 109 additions & 0 deletions src/keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//! Key structures for Orchard.

use crate::address::Address;

/// 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;

#[derive(Debug)]
pub(crate) struct SpendAuthorizingKey;

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;

impl From<&SpendAuthorizingKey> for AuthorizingKey {
fn from(_: &SpendAuthorizingKey) -> Self {
todo!()
}
}

#[derive(Debug)]
pub(crate) struct NullifierDerivingKey;

impl From<&SpendingKey> for NullifierDerivingKey {
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
/// 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)]
pub struct FullViewingKey {
ak: AuthorizingKey,
nk: NullifierDerivingKey,
rivk: (),
}

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`].
#[derive(Debug)]
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.
///
/// 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 on its own in a wallet, as it cannot maintain
/// accurate balance. You should use a [`FullViewingKey`] instead.
#[derive(Debug)]
pub struct IncomingViewingKey;

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!()
}
}

/// 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!()
}
}
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(unsafe_code)]

mod address;
pub mod bundle;
mod circuit;
pub mod keys;
mod note;
pub mod primitives;
mod tree;
pub mod value;

pub use address::Address;
pub use note::{EncryptedNote, Note, NoteCommitment, Nullifier};
61 changes: 61 additions & 0 deletions src/note.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
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 {
/// The recipient of the funds.
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 {
/// 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;
7 changes: 7 additions & 0 deletions src/primitives.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Primitives used in the Orchard protocol.
// TODO:
// - DH stuff
// - EphemeralPublicKey
// - EphemeralSecretKey

pub mod redpallas;
45 changes: 45 additions & 0 deletions src/primitives/redpallas.rs
Original file line number Diff line number Diff line change
@@ -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: SigType> {
_t: PhantomData<T>,
}

/// A RedPallas verification key.
#[derive(Debug)]
pub struct VerificationKey<T: SigType> {
_t: PhantomData<T>,
}

/// A RedPallas signature.
#[derive(Debug)]
pub struct Signature<T: SigType> {
_t: PhantomData<T>,
}

pub(crate) mod private {
use super::{Binding, SpendAuth};

pub trait Sealed {}

impl Sealed for SpendAuth {}

impl Sealed for Binding {}
}
3 changes: 3 additions & 0 deletions src/tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// The root of an Orchard commitment tree.
#[derive(Debug)]
pub struct Anchor;
26 changes: 26 additions & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! 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

/// The value of an individual Orchard note.
#[derive(Debug)]
pub struct NoteValue(u64);

/// A sum of Orchard note values.
#[derive(Debug)]
pub struct ValueSum(i64);

/// A commitment to a [`ValueSum`].
#[derive(Debug)]
pub struct ValueCommitment;

0 comments on commit 744b39d

Please sign in to comment.