Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ debug = true
debug = true

[patch.crates-io]
zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/librustzcash.git", tag = "orchard_zsa_0.5.0_compatible" }
zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/librustzcash.git", branch = "zsa-bundle-in-v5-vector-serialization" }
26 changes: 10 additions & 16 deletions src/bundle/commitments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ pub fn hash_bundle_auth_empty() -> Blake2bHash {
hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION).finalize()
}

/// Construct the commitment for an absent issue bundle
pub fn hash_issue_bundle_auth_empty() -> Blake2bHash {
hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize()
}

/// Construct the commitment for the absent issue bundle
pub fn hash_issue_bundle_txid_empty() -> Blake2bHash {
hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize()
}

/// Construct the commitment for the issue bundle
pub(crate) fn hash_issue_bundle_txid_data<A: IssueAuth>(bundle: &IssueBundle<A>) -> Blake2bHash {
let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION);
Expand All @@ -119,26 +129,10 @@ pub(crate) fn hash_issue_bundle_txid_data<A: IssueAuth>(bundle: &IssueBundle<A>)
h.finalize()
}

/// Construct the commitment for the absent issue bundle as defined in
/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227]
///
/// [zip227]: https://qed-it.github.io/zips/zip-0227
pub fn hash_issue_bundle_txid_empty() -> Blake2bHash {
hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize()
}

/// Construct the commitment to the authorizing data of an
/// authorized issue bundle
pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle<Signed>) -> Blake2bHash {
let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION);
h.update(&<[u8; 64]>::from(bundle.authorization().signature()));
h.finalize()
}

/// Construct the commitment for an absent issue bundle as defined in
/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227]
///
/// [zip227]: https://qed-it.github.io/zips/zip-0227
pub fn hash_issue_bundle_auth_empty() -> Blake2bHash {
hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION).finalize()
}
78 changes: 70 additions & 8 deletions src/issuance.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Structs related to issuance bundles and the associated logic.
use blake2b_simd::Hash as Blake2bHash;
use group::Group;
use memuse::DynamicUsage;
use nonempty::NonEmpty;
use rand::{CryptoRng, RngCore};
use std::collections::HashSet;
Expand Down Expand Up @@ -49,6 +50,25 @@ pub struct IssueAction {
finalize: bool,
}

impl DynamicUsage for IssueAction {
#[inline(always)]
fn dynamic_usage(&self) -> usize {
self.asset_desc.dynamic_usage() + self.notes.dynamic_usage()
}

#[inline(always)]
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
let bounds = (
self.asset_desc.dynamic_usage_bounds(),
self.notes.dynamic_usage_bounds(),
);
(
bounds.0 .0 + bounds.1 .0,
bounds.0 .1.zip(bounds.1 .1).map(|(a, b)| a + b),
)
}
}

/// The parameters required to add a Note into an IssueAction.
#[derive(Debug)]
pub struct IssueInfo {
Expand Down Expand Up @@ -197,6 +217,15 @@ impl IssueAuth for Unauthorized {}
impl IssueAuth for Prepared {}
impl IssueAuth for Signed {}

impl DynamicUsage for Signed {
fn dynamic_usage(&self) -> usize {
0
}
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

impl<T: IssueAuth> IssueBundle<T> {
/// Returns the issuer verification key for the bundle.
pub fn ik(&self) -> &IssuanceValidatingKey {
Expand Down Expand Up @@ -455,6 +484,29 @@ impl IssueBundle<Signed> {
}
}

impl DynamicUsage for IssueBundle<Signed> {
fn dynamic_usage(&self) -> usize {
self.actions.dynamic_usage() + self.ik.dynamic_usage() + self.authorization.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
let bounds = (
self.actions.dynamic_usage_bounds(),
self.ik.dynamic_usage_bounds(),
self.authorization.dynamic_usage_bounds(),
);
(
bounds.0 .0 + bounds.1 .0 + bounds.2 .0,
bounds
.0
.1
.zip(bounds.1 .1)
.zip(bounds.2 .1)
.map(|((a, b), c)| a + b + c),
)
}
}

/// Validation for Orchard IssueBundles
///
/// A set of previously finalized asset types must be provided in `finalized` argument.
Expand Down Expand Up @@ -1395,14 +1447,27 @@ mod tests {
#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))]
pub mod testing {
use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized};
use crate::keys::testing::{arb_issuance_authorizing_key, arb_issuance_validating_key};
use crate::keys::testing::arb_issuance_validating_key;
use crate::note::asset_base::testing::zsa_asset_id;
use crate::note::testing::arb_zsa_note;
use crate::primitives::redpallas::Signature;
use nonempty::NonEmpty;
use proptest::collection::vec;
use proptest::prelude::*;
use proptest::prop_compose;
use rand::{rngs::StdRng, SeedableRng};
use reddsa::orchard::SpendAuth;

prop_compose! {
/// Generate a uniformly distributed signature
pub(crate) fn arb_signature()(
half_bytes in prop::array::uniform32(prop::num::u8::ANY)
) -> Signature<SpendAuth> {
// prop::array can only generate 32 elements max, so we duplicate it
let sig_bytes: [u8; 64] = [half_bytes, half_bytes].concat().try_into().unwrap();
let sig: Signature<SpendAuth> = Signature::from(sig_bytes);
sig
}
}

prop_compose! {
/// Generate an issue action
Expand Down Expand Up @@ -1462,17 +1527,14 @@ pub mod testing {
(
actions in vec(arb_issue_action("asset_desc".to_string()), n_actions),
ik in arb_issuance_validating_key(),
isk in arb_issuance_authorizing_key(),
rng_seed in prop::array::uniform32(prop::num::u8::ANY),
fake_sighash in prop::array::uniform32(prop::num::u8::ANY)
fake_sig in arb_signature(),
) -> IssueBundle<Signed> {
let rng = StdRng::from_seed(rng_seed);
let actions = NonEmpty::from_vec(actions).unwrap();
IssueBundle {
ik,
actions,
authorization: Prepared { sighash: fake_sighash },
}.sign(rng, &isk).unwrap()
authorization: Signed { signature: fake_sig },
}
}
}
}
13 changes: 13 additions & 0 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use group::{
prime::PrimeCurveAffine,
Curve, GroupEncoding,
};
use memuse::DynamicUsage;
use pasta_curves::{pallas, pallas::Scalar};
use rand::{CryptoRng, RngCore};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
Expand Down Expand Up @@ -349,6 +350,18 @@ impl PartialEq for IssuanceValidatingKey {

impl Eq for IssuanceValidatingKey {}

impl DynamicUsage for IssuanceValidatingKey {
#[inline(always)]
fn dynamic_usage(&self) -> usize {
0
}

#[inline(always)]
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

impl IssuanceValidatingKey {
/// Converts this spend validating key to its serialized form,
/// I2LEOSP_256(ik).
Expand Down
13 changes: 13 additions & 0 deletions src/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use core::fmt;

use group::GroupEncoding;
use memuse::DynamicUsage;
use pasta_curves::pallas;
use rand::RngCore;
use subtle::{Choice, ConditionallySelectable, CtOption};
Expand Down Expand Up @@ -306,6 +307,18 @@ impl Note {
}
}

impl DynamicUsage for Note {
#[inline(always)]
fn dynamic_usage(&self) -> usize {
0
}

#[inline(always)]
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

/// An encrypted note.
#[derive(Clone)]
pub struct TransmittedNoteCiphertext {
Expand Down