mirror of https://github.com/zcash/orchard.git
commit
744b39db9f
|
@ -0,0 +1,8 @@
|
|||
use crate::keys::Diversifier;
|
||||
|
||||
/// A shielded payment address.
|
||||
#[derive(Debug)]
|
||||
pub struct Address {
|
||||
d: Diversifier,
|
||||
pk_d: (),
|
||||
}
|
|
@ -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;
|
|
@ -0,0 +1,2 @@
|
|||
#[derive(Debug)]
|
||||
pub struct Proof(Vec<u8>);
|
|
@ -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
src/lib.rs
12
src/lib.rs
|
@ -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};
|
||||
|
|
|
@ -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;
|
|
@ -0,0 +1,7 @@
|
|||
//! Primitives used in the Orchard protocol.
|
||||
// TODO:
|
||||
// - DH stuff
|
||||
// - EphemeralPublicKey
|
||||
// - EphemeralSecretKey
|
||||
|
||||
pub mod redpallas;
|
|
@ -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 {}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
/// The root of an Orchard commitment tree.
|
||||
#[derive(Debug)]
|
||||
pub struct Anchor;
|
|
@ -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;
|
Loading…
Reference in New Issue