Skip to content

Commit

Permalink
Merge pull request #1670 from zcash/pczt-redactor
Browse files Browse the repository at this point in the history
pczt: Add a Redactor role
  • Loading branch information
nuttycom authored Dec 19, 2024
2 parents eee19d9 + 9c6d1b9 commit 9c564df
Show file tree
Hide file tree
Showing 7 changed files with 824 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pczt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this library adheres to Rust's notion of

## [Unreleased]

### Added
- `pczt::roles::redactor`

### Changed
- Migrated to `nonempty 0.11`

Expand Down
5 changes: 5 additions & 0 deletions pczt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
//! - Updater (anyone can contribute)
//! - Adds information necessary for subsequent entities to proceed, such as key paths
//! for signing spends.
//! - Redactor (anyone can execute)
//! - Removes information that is unnecessary for subsequent entities to proceed.
//! - This can be useful e.g. when creating a transaction that has inputs from multiple
//! independent Signers; each can receive a PCZT with just the information they need
//! to sign, but (e.g.) not the `alpha` values for other Signers.
//! - Prover (capability holders can contribute)
//! - Needs all private information for a single spend or output.
//! - In practice, the Updater that adds a given spend or output will either act as
Expand Down
2 changes: 2 additions & 0 deletions pczt/src/roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub mod verifier;

pub mod updater;

pub mod redactor;

#[cfg(feature = "prover")]
pub mod prover;

Expand Down
45 changes: 45 additions & 0 deletions pczt/src/roles/redactor/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::{common::Global, Pczt};

pub mod orchard;
pub mod sapling;
pub mod transparent;

pub struct Redactor {
pczt: Pczt,
}

impl Redactor {
/// Instantiates the Redactor role with the given PCZT.
pub fn new(pczt: Pczt) -> Self {
Self { pczt }
}

/// Redacts the global transaction details with the given closure.
pub fn redact_global_with<F>(mut self, f: F) -> Self
where
F: FnOnce(GlobalRedactor<'_>),
{
f(GlobalRedactor(&mut self.pczt.global));
self
}

/// Finishes the Redactor role, returning the redacted PCZT.
pub fn finish(self) -> Pczt {
self.pczt
}
}

/// An Redactor for the global transaction details.
pub struct GlobalRedactor<'a>(&'a mut Global);

impl<'a> GlobalRedactor<'a> {
/// Redacts the proprietary value at the given key.
pub fn redact_proprietary(&mut self, key: &str) {
self.0.proprietary.remove(key);
}

/// Removes all proprietary values.
pub fn clear_proprietary(&mut self) {
self.0.proprietary.clear();
}
}
222 changes: 222 additions & 0 deletions pczt/src/roles/redactor/orchard.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
use crate::orchard::{Action, Bundle};

impl super::Redactor {
/// Redacts the Orchard bundle with the given closure.
pub fn redact_orchard_with<F>(mut self, f: F) -> Self
where
F: FnOnce(OrchardRedactor<'_>),
{
f(OrchardRedactor(&mut self.pczt.orchard));
self
}
}

/// A Redactor for the Orchard bundle.
pub struct OrchardRedactor<'a>(&'a mut Bundle);

impl<'a> OrchardRedactor<'a> {
/// Redacts all actions in the same way.
pub fn redact_actions<F>(&mut self, f: F)
where
F: FnOnce(ActionRedactor<'_>),
{
f(ActionRedactor(Actions::All(&mut self.0.actions)));
}

/// Redacts the action at the given index.
///
/// Does nothing if the index is out of range.
pub fn redact_action<F>(&mut self, index: usize, f: F)
where
F: FnOnce(ActionRedactor<'_>),
{
if let Some(action) = self.0.actions.get_mut(index) {
f(ActionRedactor(Actions::One(action)));
}
}

/// Removes the proof.
pub fn clear_zkproof(&mut self) {
self.0.zkproof = None;
}

/// Removes the proof.
pub fn clear_bsk(&mut self) {
self.0.bsk = None;
}
}

/// A Redactor for Orchard actions.
pub struct ActionRedactor<'a>(Actions<'a>);

enum Actions<'a> {
All(&'a mut [Action]),
One(&'a mut Action),
}

impl<'a> ActionRedactor<'a> {
fn redact<F>(&mut self, f: F)
where
F: Fn(&mut Action),
{
match &mut self.0 {
Actions::All(actions) => {
for action in actions.iter_mut() {
f(action);
}
}
Actions::One(action) => {
f(action);
}
}
}

/// Removes the spend authorizing signature.
pub fn clear_spend_auth_sig(&mut self) {
self.redact(|action| {
action.spend.spend_auth_sig = None;
});
}

/// Removes the spend's recipient.
pub fn clear_spend_recipient(&mut self) {
self.redact(|action| {
action.spend.recipient = None;
});
}

/// Removes the spend's value.
pub fn clear_spend_value(&mut self) {
self.redact(|action| {
action.spend.value = None;
});
}

/// Removes the rho value for the note being spent.
pub fn clear_spend_rho(&mut self) {
self.redact(|action| {
action.spend.rho = None;
});
}

/// Removes the seed randomness for the note being spent.
pub fn clear_spend_rseed(&mut self) {
self.redact(|action| {
action.spend.rseed = None;
});
}

/// Removes the spend's full viewing key.
pub fn clear_spend_fvk(&mut self) {
self.redact(|action| {
action.spend.fvk = None;
});
}

/// Removes the witness from the spent note to the bundle's anchor.
pub fn clear_spend_witness(&mut self) {
self.redact(|action| {
action.spend.witness = None;
});
}

/// Removes the spend authorization randomizer.
pub fn clear_spend_alpha(&mut self) {
self.redact(|action| {
action.spend.alpha = None;
});
}

/// Removes the ZIP 32 derivation path at which the spending key can be found for the
/// note being spent.
pub fn clear_spend_zip32_derivation(&mut self) {
self.redact(|action| {
action.spend.zip32_derivation = None;
});
}

/// Removes the spending key for this spent note, if it is a dummy note.
pub fn clear_spend_dummy_sk(&mut self) {
self.redact(|action| {
action.spend.dummy_sk = None;
});
}

/// Redacts the spend-specific proprietary value at the given key.
pub fn redact_spend_proprietary(&mut self, key: &str) {
self.redact(|action| {
action.spend.proprietary.remove(key);
});
}

/// Removes all spend-specific proprietary values.
pub fn clear_spend_proprietary(&mut self) {
self.redact(|action| {
action.spend.proprietary.clear();
});
}

/// Removes the output's recipient.
pub fn clear_output_recipient(&mut self) {
self.redact(|action| {
action.output.recipient = None;
});
}

/// Removes the output's value.
pub fn clear_output_value(&mut self) {
self.redact(|action| {
action.output.value = None;
});
}

/// Removes the seed randomness for the note being created.
pub fn clear_output_rseed(&mut self) {
self.redact(|action| {
action.output.rseed = None;
});
}

/// Removes the `ock` value used to encrypt `out_ciphertext`.
pub fn clear_output_ock(&mut self) {
self.redact(|action| {
action.output.ock = None;
});
}

/// Removes the ZIP 32 derivation path at which the spending key can be found for the
/// note being created.
pub fn clear_output_zip32_derivation(&mut self) {
self.redact(|action| {
action.output.zip32_derivation = None;
});
}

/// Removes the user-facing address to which the output is being sent, if any.
pub fn clear_output_user_address(&mut self) {
self.redact(|spend| {
spend.output.user_address = None;
});
}

/// Redacts the output-specific proprietary value at the given key.
pub fn redact_output_proprietary(&mut self, key: &str) {
self.redact(|action| {
action.output.proprietary.remove(key);
});
}

/// Removes all output-specific proprietary values.
pub fn clear_output_proprietary(&mut self) {
self.redact(|action| {
action.output.proprietary.clear();
});
}

/// Removes the value commitment randomness.
pub fn clear_rcv(&mut self) {
self.redact(|action| {
action.rcv = None;
});
}
}
Loading

0 comments on commit 9c564df

Please sign in to comment.