Skip to content

Commit

Permalink
Merge pull request #507 from nuttycom/map_authorization
Browse files Browse the repository at this point in the history
Define transaction::TransactionData::map_authorization
  • Loading branch information
str4d committed Feb 12, 2022
2 parents caba2dc + 54e3dde commit 3d935a9
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 0 deletions.
10 changes: 10 additions & 0 deletions zcash_primitives/src/extensions/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ pub struct Witness<T> {
pub payload: T,
}

impl<T> Witness<T> {
pub fn map_payload<U, F: FnOnce(T) -> U>(self, f: F) -> Witness<U> {
Witness {
extension_id: self.extension_id,
mode: self.mode,
payload: f(self.payload),
}
}
}

impl Witness<AuthData> {
/// Produce the intermediate format for an extension-specific witness
/// type.
Expand Down
5 changes: 5 additions & 0 deletions zcash_primitives/src/transaction/components/orchard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ impl Authorization for Unauthorized {
type SpendAuth = ();
}

pub trait MapAuth<A: Authorization, B: Authorization> {
fn map_spend_auth(&self, s: A::SpendAuth) -> B::SpendAuth;
fn map_authorization(&self, a: A) -> B;
}

/// Reads an [`orchard::Bundle`] from a v5 transaction format.
pub fn read_v5_bundle<R: Read>(
mut reader: R,
Expand Down
39 changes: 39 additions & 0 deletions zcash_primitives/src/transaction/components/sapling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ impl Authorization for Authorized {
type AuthSig = redjubjub::Signature;
}

pub trait MapAuth<A: Authorization, B: Authorization> {
fn map_proof(&self, p: A::Proof) -> B::Proof;
fn map_auth_sig(&self, s: A::AuthSig) -> B::AuthSig;
fn map_authorization(&self, a: A) -> B;
}

#[derive(Debug, Clone)]
pub struct Bundle<A: Authorization> {
pub shielded_spends: Vec<SpendDescription<A>>,
Expand All @@ -55,6 +61,39 @@ pub struct Bundle<A: Authorization> {
pub authorization: A,
}

impl<A: Authorization> Bundle<A> {
pub fn map_authorization<B: Authorization, F: MapAuth<A, B>>(self, f: F) -> Bundle<B> {
Bundle {
shielded_spends: self
.shielded_spends
.into_iter()
.map(|d| SpendDescription {
cv: d.cv,
anchor: d.anchor,
nullifier: d.nullifier,
rk: d.rk,
zkproof: f.map_proof(d.zkproof),
spend_auth_sig: f.map_auth_sig(d.spend_auth_sig),
})
.collect(),
shielded_outputs: self
.shielded_outputs
.into_iter()
.map(|o| OutputDescription {
cv: o.cv,
cmu: o.cmu,
ephemeral_key: o.ephemeral_key,
enc_ciphertext: o.enc_ciphertext,
out_ciphertext: o.out_ciphertext,
zkproof: f.map_proof(o.zkproof),
})
.collect(),
value_balance: self.value_balance,
authorization: f.map_authorization(self.authorization),
}
}
}

#[derive(Clone)]
pub struct SpendDescription<A: Authorization> {
pub cv: jubjub::ExtendedPoint,
Expand Down
23 changes: 23 additions & 0 deletions zcash_primitives/src/transaction/components/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,36 @@ impl Authorization for Authorized {
type ScriptSig = Script;
}

pub trait MapAuth<A: Authorization, B: Authorization> {
fn map_script_sig(&self, s: A::ScriptSig) -> B::ScriptSig;
fn map_authorization(&self, s: A) -> B;
}

#[derive(Debug, Clone, PartialEq)]
pub struct Bundle<A: Authorization> {
pub vin: Vec<TxIn<A>>,
pub vout: Vec<TxOut>,
pub authorization: A,
}

impl<A: Authorization> Bundle<A> {
pub fn map_authorization<B: Authorization, F: MapAuth<A, B>>(self, f: F) -> Bundle<B> {
Bundle {
vin: self
.vin
.into_iter()
.map(|txin| TxIn {
prevout: txin.prevout,
script_sig: f.map_script_sig(txin.script_sig),
sequence: txin.sequence,
})
.collect(),
vout: self.vout,
authorization: f.map_authorization(self.authorization),
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct OutPoint {
hash: [u8; 32],
Expand Down
22 changes: 22 additions & 0 deletions zcash_primitives/src/transaction/components/tze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,35 @@ impl Authorization for Authorized {
type Witness = tze::AuthData;
}

pub trait MapAuth<A: Authorization, B: Authorization> {
fn map_witness(&self, s: A::Witness) -> B::Witness;
fn map_authorization(&self, s: A) -> B;
}

#[derive(Debug, Clone, PartialEq)]
pub struct Bundle<A: Authorization> {
pub vin: Vec<TzeIn<A::Witness>>,
pub vout: Vec<TzeOut>,
pub authorization: A,
}

impl<A: Authorization> Bundle<A> {
pub fn map_authorization<B: Authorization, F: MapAuth<A, B>>(self, f: F) -> Bundle<B> {
Bundle {
vin: self
.vin
.into_iter()
.map(|tzein| TzeIn {
prevout: tzein.prevout,
witness: tzein.witness.map_payload(|p| f.map_witness(p)),
})
.collect(),
vout: self.vout,
authorization: f.map_authorization(self.authorization),
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct OutPoint {
txid: TxId,
Expand Down
66 changes: 66 additions & 0 deletions zcash_primitives/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,68 @@ impl<A: Authorization> TransactionData<A> {
digester.digest_tze(self.tze_bundle.as_ref()),
)
}

/// Maps the bundles from one type to another.
///
/// This shouldn't be necessary for most use cases; it is provided for handling the
/// cross-FFI builder logic in `zcashd`.
pub fn map_bundles<B: Authorization>(
self,
f_transparent: impl FnOnce(
Option<transparent::Bundle<A::TransparentAuth>>,
) -> Option<transparent::Bundle<B::TransparentAuth>>,
f_sapling: impl FnOnce(
Option<sapling::Bundle<A::SaplingAuth>>,
) -> Option<sapling::Bundle<B::SaplingAuth>>,
f_orchard: impl FnOnce(
Option<orchard::bundle::Bundle<A::OrchardAuth, Amount>>,
) -> Option<orchard::bundle::Bundle<B::OrchardAuth, Amount>>,
#[cfg(feature = "zfuture")] f_tze: impl FnOnce(
Option<tze::Bundle<A::TzeAuth>>,
) -> Option<tze::Bundle<B::TzeAuth>>,
) -> TransactionData<B> {
TransactionData {
version: self.version,
consensus_branch_id: self.consensus_branch_id,
lock_time: self.lock_time,
expiry_height: self.expiry_height,
transparent_bundle: f_transparent(self.transparent_bundle),
sprout_bundle: self.sprout_bundle,
sapling_bundle: f_sapling(self.sapling_bundle),
orchard_bundle: f_orchard(self.orchard_bundle),
#[cfg(feature = "zfuture")]
tze_bundle: f_tze(self.tze_bundle),
}
}

pub fn map_authorization<B: Authorization>(
self,
f_transparent: impl transparent::MapAuth<A::TransparentAuth, B::TransparentAuth>,
f_sapling: impl sapling::MapAuth<A::SaplingAuth, B::SaplingAuth>,
mut f_orchard: impl orchard_serialization::MapAuth<A::OrchardAuth, B::OrchardAuth>,
#[cfg(feature = "zfuture")] f_tze: impl tze::MapAuth<A::TzeAuth, B::TzeAuth>,
) -> TransactionData<B> {
TransactionData {
version: self.version,
consensus_branch_id: self.consensus_branch_id,
lock_time: self.lock_time,
expiry_height: self.expiry_height,
transparent_bundle: self
.transparent_bundle
.map(|b| b.map_authorization(f_transparent)),
sprout_bundle: self.sprout_bundle,
sapling_bundle: self.sapling_bundle.map(|b| b.map_authorization(f_sapling)),
orchard_bundle: self.orchard_bundle.map(|b| {
b.authorize(
&mut f_orchard,
|f, _, s| f.map_spend_auth(s),
|f, a| f.map_authorization(a),
)
}),
#[cfg(feature = "zfuture")]
tze_bundle: self.tze_bundle.map(|b| b.map_authorization(f_tze)),
}
}
}

impl<A: Authorization> std::fmt::Debug for TransactionData<A> {
Expand Down Expand Up @@ -505,6 +567,10 @@ impl Transaction {
Transaction { txid, data }
}

pub fn into_data(self) -> TransactionData<Authorized> {
self.data
}

pub fn txid(&self) -> TxId {
self.txid
}
Expand Down

0 comments on commit 3d935a9

Please sign in to comment.