Skip to content

Commit

Permalink
Revert "Revert "Add hashing of burn field to hash_bundle_txid_data""
Browse files Browse the repository at this point in the history
This reverts commit 8795ca4.
  • Loading branch information
dmidem committed Apr 17, 2024
1 parent 58e05b1 commit e67c792
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 10 deletions.
16 changes: 11 additions & 5 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use zcash_note_encryption_zsa::NoteEncryption;
use crate::{
action::Action,
address::Address,
bundle::{Authorization, Authorized, Bundle, Flags},
bundle::{Authorization, Authorized, Bundle, Flags, OrchardHash},
circuit::{Instance, OrchardCircuit, OrchardCircuitBase, Proof, ProvingKey},
keys::{
FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey,
Expand Down Expand Up @@ -485,7 +485,10 @@ impl Builder {
///
/// The returned bundle will have no proof or signatures; these can be applied with
/// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively.
pub fn build<V: TryFrom<i64> + Copy + Into<i64>, D: OrchardDomain + OrchardCircuit>(
pub fn build<
V: TryFrom<i64> + Copy + Into<i64>,
D: OrchardDomain + OrchardCircuit + OrchardHash,
>(
self,
mut rng: impl RngCore,
) -> Result<UnauthorizedBundle<V, D>, BuildError> {
Expand Down Expand Up @@ -929,7 +932,7 @@ pub mod testing {
use crate::note::AssetBase;
use crate::{
address::testing::arb_address,
bundle::{Authorized, Bundle, Flags},
bundle::{Authorized, Bundle, Flags, OrchardHash},
circuit::{OrchardCircuit, ProvingKey},
keys::{testing::arb_spending_key, FullViewingKey, SpendAuthorizingKey, SpendingKey},
note::testing::arb_note,
Expand Down Expand Up @@ -960,7 +963,10 @@ pub mod testing {

impl<R: RngCore + CryptoRng> ArbitraryBundleInputs<R> {
/// Create a bundle from the set of arbitrary bundle inputs.
fn into_bundle<V: TryFrom<i64> + Copy + Into<i64>, D: OrchardDomain + OrchardCircuit>(
fn into_bundle<
V: TryFrom<i64> + Copy + Into<i64>,
D: OrchardDomain + OrchardCircuit + OrchardHash,
>(
mut self,
) -> Bundle<Authorized, V, D> {
let fvk = FullViewingKey::from(&self.sk);
Expand Down Expand Up @@ -1003,7 +1009,7 @@ pub mod testing {
phantom: std::marker::PhantomData<D>,
}

impl<D: OrchardDomain + OrchardCircuit> BuilderArb<D> {
impl<D: OrchardDomain + OrchardCircuit + OrchardHash> BuilderArb<D> {
prop_compose! {
/// Produce a random valid Orchard bundle.
fn arb_bundle_inputs(sk: SpendingKey)
Expand Down
4 changes: 3 additions & 1 deletion src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use crate::{
value::{ValueCommitTrapdoor, ValueCommitment, ValueSum},
};

pub use commitments::OrchardHash;

impl<A, D: OrchardDomain> Action<A, D> {
/// Prepares the public instance for this action, for creating and verifying the
/// bundle proof.
Expand Down Expand Up @@ -404,7 +406,7 @@ impl<A: Authorization, V, D: OrchardDomain> Bundle<A, V, D> {
}
}

impl<A: Authorization, V: Copy + Into<i64>, D: OrchardDomain> Bundle<A, V, D> {
impl<A: Authorization, V: Copy + Into<i64>, D: OrchardDomain + OrchardHash> Bundle<A, V, D> {
/// Computes a commitment to the effects of this bundle, suitable for inclusion within
/// a transaction ID.
pub fn commitment(&self) -> BundleCommitment {
Expand Down
3 changes: 2 additions & 1 deletion src/bundle/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use tracing::debug;
use super::{Authorized, Bundle};

use crate::{
bundle::OrchardHash,
circuit::VerifyingKey,
note_encryption::OrchardDomain,
primitives::redpallas::{self, Binding, SpendAuth},
Expand Down Expand Up @@ -37,7 +38,7 @@ impl BatchValidator {
}

/// Adds the proof and RedPallas signatures from the given bundle to the validator.
pub fn add_bundle<V: Copy + Into<i64>, D: OrchardDomain>(
pub fn add_bundle<V: Copy + Into<i64>, D: OrchardDomain + OrchardHash>(
&mut self,
bundle: &Bundle<Authorized, V, D>,
sighash: [u8; 32],
Expand Down
56 changes: 53 additions & 3 deletions src/bundle/commitments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ use zcash_note_encryption_zsa::MEMO_SIZE;
use crate::{
bundle::{Authorization, Authorized, Bundle},
issuance::{IssueAuth, IssueBundle, Signed},
note::AssetBase,
note_encryption::OrchardDomain,
orchard_flavor::{OrchardVanilla, OrchardZSA},
};

const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash";
const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActCHash";
const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash";
const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash";
const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash";
const ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcBurnHash";
const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdSAIssueHash";
const ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION: &[u8; 16] = b"ZTxIdIssuActHash";
const ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION: &[u8; 16] = b"ZTxIdIAcNoteHash";
Expand All @@ -24,6 +27,40 @@ fn hasher(personal: &[u8; 16]) -> State {
Params::new().hash_length(32).personal(personal).to_state()
}

// FIXME: Consider not using a separate OrchardHash trait and instead move update_hash_with_burn to
// the OrchardDomain or OrchardFlavour trait.

/// Manages the hashing of ZSA burn-related data in transactions.
pub trait OrchardHash {
/// Incorporates the hash of burn items into the main transaction hash.
fn update_hash_with_burn<V: Copy + Into<i64>>(
main_hasher: &mut State,
burn_items: &[(AssetBase, V)],
);
}

impl OrchardHash for OrchardVanilla {
fn update_hash_with_burn<V: Copy + Into<i64>>(
_main_hasher: &mut State,
_burn_items: &[(AssetBase, V)],
) {
}
}

impl OrchardHash for OrchardZSA {
fn update_hash_with_burn<V: Copy + Into<i64>>(
main_hasher: &mut State,
burn_items: &[(AssetBase, V)],
) {
let mut burn_hasher = hasher(ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION);
for burn_item in burn_items {
burn_hasher.update(&burn_item.0.to_bytes());
burn_hasher.update(&burn_item.1.into().to_le_bytes());
}
main_hasher.update(burn_hasher.finalize().as_bytes());
}
}

/// Write disjoint parts of each Orchard shielded action as 3 separate hashes:
/// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized
/// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION
Expand All @@ -33,11 +70,20 @@ fn hasher(personal: &[u8; 16]) -> State {
/// with ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION
/// as defined in [ZIP-244: Transaction Identifier Non-Malleability][zip244]
///
/// Then, hash these together along with (flags, value_balance_orchard, anchor_orchard),
/// personalized with ZCASH_ORCHARD_ACTIONS_HASH_PERSONALIZATION
/// These hashes are combined with additional data, which may include the ZSA burn field for specific
/// Orchard variants (see ZIP-226), flags, value_balance_orchard, and anchor_orchard. The inclusion of
/// the burn field is dependent on the specific implementation of the `OrchardHash` trait, which
/// defines whether the burn field should be included based on the variant (ZSA variant includes it).
///
/// The final hash is personalized with ZCASH_ORCHARD_HASH_PERSONALIZATION.
///
/// [zip244]: https://zips.z.cash/zip-0244
pub(crate) fn hash_bundle_txid_data<A: Authorization, V: Copy + Into<i64>, D: OrchardDomain>(
/// [zip226]: https://zips.z.cash/zip-0226 (for ZSA burn field hashing)
pub(crate) fn hash_bundle_txid_data<
A: Authorization,
V: Copy + Into<i64>,
D: OrchardDomain + OrchardHash,
>(
bundle: &Bundle<A, V, D>,
) -> Blake2bHash {
let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION);
Expand Down Expand Up @@ -68,6 +114,10 @@ pub(crate) fn hash_bundle_txid_data<A: Authorization, V: Copy + Into<i64>, D: Or
h.update(ch.finalize().as_bytes());
h.update(mh.finalize().as_bytes());
h.update(nh.finalize().as_bytes());

// Delegate complete handling of the burn data to the OrchardHash implementation
D::update_hash_with_burn(&mut h, &bundle.burn);

h.update(&[bundle.flags().to_byte()]);
h.update(&(*bundle.value_balance()).into().to_le_bytes());
h.update(&bundle.anchor().to_bytes());
Expand Down

0 comments on commit e67c792

Please sign in to comment.