Skip to content

Commit

Permalink
[ZIP-233] Add burn_amount to transaction fields
Browse files Browse the repository at this point in the history
  • Loading branch information
tomekpiotrowski authored and giddie committed Oct 11, 2024
1 parent 81d8ad4 commit 0ac99f7
Show file tree
Hide file tree
Showing 16 changed files with 2,668 additions and 128 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,4 @@ panic = 'abort'
codegen-units = 1

[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("zfuture"))'] }
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("zfuture", "tze", "nsm"))'] }
3 changes: 3 additions & 0 deletions components/zcash_protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ test-dependencies = [

## Exposes support for working with a local consensus (e.g. regtest).
local-consensus = []

[lints]
workspace = true
2 changes: 2 additions & 0 deletions components/zcash_protocol/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ const UPGRADES_IN_ORDER: &[NetworkUpgrade] = &[
NetworkUpgrade::Canopy,
NetworkUpgrade::Nu5,
NetworkUpgrade::Nu6,
#[cfg(zcash_unstable = "zfuture")]
NetworkUpgrade::ZFuture,
];

/// The "grace period" defined in [ZIP 212].
Expand Down
6 changes: 3 additions & 3 deletions devtools/src/bin/inspect/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
GROTH16_PARAMS, ORCHARD_VK,
};

#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]
use zcash_primitives::transaction::components::tze;

pub fn is_coinbase(tx: &Transaction) -> bool {
Expand Down Expand Up @@ -148,7 +148,7 @@ impl Authorization for PrecomputedAuth {
type SaplingAuth = sapling::bundle::Authorized;
type OrchardAuth = orchard::bundle::Authorized;

#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]
type TzeAuth = tze::Authorized;
}

Expand Down Expand Up @@ -211,7 +211,7 @@ pub(crate) fn inspect(
f_transparent,
(),
(),
#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]

Check warning on line 214 in devtools/src/bin/inspect/transaction.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/transaction.rs#L214

Added line #L214 was not covered by tests
(),
);
let txid_parts = tx.digest(TxIdDigester);
Expand Down
4 changes: 4 additions & 0 deletions zcash_client_sqlite/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,10 @@ pub(crate) fn get_transaction<P: Parameters>(
tx_data.sprout_bundle().cloned(),
tx_data.sapling_bundle().cloned(),
tx_data.orchard_bundle().cloned(),
#[cfg(zcash_unstable = "nsm")]
tx_data.burn_amount(),
#[cfg(zcash_unstable = "tze")]
tx_data.tze_bundle().cloned(),

Check warning on line 1662 in zcash_client_sqlite/src/wallet.rs

View check run for this annotation

Codecov / codecov/patch

zcash_client_sqlite/src/wallet.rs#L1659-L1662

Added lines #L1659 - L1662 were not covered by tests
)
.freeze()
.map(|t| (expiry_height, t))
Expand Down
4 changes: 4 additions & 0 deletions zcash_client_sqlite/src/wallet/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,10 @@ mod tests {
None,
None,
None,
#[cfg(zcash_unstable = "nsm")]
None,
#[cfg(zcash_unstable = "tze")]
None,
)
.freeze()
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ mod tests {
None,
None,
None,
#[cfg(zcash_unstable = "nsm")] None,
#[cfg(zcash_unstable = "tze")] None,
));

// Check that we can apply this migration.
Expand Down
4 changes: 2 additions & 2 deletions zcash_extensions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// For workspace compilation reasons, we have this crate in the workspace and just leave
// it empty if `zfuture` is not enabled.

#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]
pub mod consensus;
#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]
pub mod transparent;
10 changes: 7 additions & 3 deletions zcash_extensions/src/transparent/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ mod tests {
precondition: tze::Precondition::from(0, &Precondition::open(hash_1)),
};

let tx_a = TransactionData::from_parts_zfuture(
let tx_a = TransactionData::from_parts(
TxVersion::ZFuture,
BranchId::ZFuture,
0,
Expand All @@ -681,6 +681,8 @@ mod tests {
None,
None,
None,
#[cfg(zcash_unstable = "nsm")]
None,
Some(Bundle {
vin: vec![],
vout: vec![out_a],
Expand All @@ -703,7 +705,7 @@ mod tests {
precondition: tze::Precondition::from(0, &Precondition::close(hash_2)),
};

let tx_b = TransactionData::from_parts_zfuture(
let tx_b = TransactionData::from_parts(
TxVersion::ZFuture,
BranchId::ZFuture,
0,
Expand All @@ -712,6 +714,8 @@ mod tests {
None,
None,
None,
#[cfg(zcash_unstable = "nsm")]
None,
Some(Bundle {
vin: vec![in_b],
vout: vec![out_b],
Expand All @@ -730,7 +734,7 @@ mod tests {
witness: tze::Witness::from(0, &Witness::close(preimage_2)),
};

let tx_c = TransactionData::from_parts_zfuture(
let tx_c = TransactionData::from_parts(
TxVersion::ZFuture,
BranchId::ZFuture,
0,
Expand Down
3 changes: 3 additions & 0 deletions zcash_primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,6 @@ harness = false

[badges]
maintenance = { status = "actively-developed" }

[lints]
workspace = true
127 changes: 123 additions & 4 deletions zcash_primitives/src/transaction/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ use crate::{
},
};

#[cfg(zcash_unstable = "nsm")]
use zcash_protocol::value::ZatBalance;

#[cfg(feature = "transparent-inputs")]
use crate::transaction::components::transparent::builder::TransparentInputInfo;

Expand Down Expand Up @@ -287,6 +290,8 @@ pub struct Builder<'a, P, U: sapling::builder::ProverProgress> {
// derivatives for proving and signing to complete transaction creation.
sapling_asks: Vec<sapling::keys::SpendAuthorizingKey>,
orchard_saks: Vec<orchard::keys::SpendAuthorizingKey>,
#[cfg(zcash_unstable = "nsm")]
burn_amount: Option<NonNegativeAmount>,
#[cfg(zcash_unstable = "zfuture")]
tze_builder: TzeBuilder<'a, TransactionData<Unauthorized>>,
#[cfg(not(zcash_unstable = "zfuture"))]
Expand Down Expand Up @@ -372,6 +377,8 @@ impl<'a, P: consensus::Parameters> Builder<'a, P, ()> {
orchard_builder,
sapling_asks: vec![],
orchard_saks: Vec::new(),
#[cfg(zcash_unstable = "nsm")]
burn_amount: None,
#[cfg(zcash_unstable = "zfuture")]
tze_builder: TzeBuilder::empty(),
#[cfg(not(zcash_unstable = "zfuture"))]
Expand Down Expand Up @@ -400,6 +407,8 @@ impl<'a, P: consensus::Parameters> Builder<'a, P, ()> {
orchard_builder: self.orchard_builder,
sapling_asks: self.sapling_asks,
orchard_saks: self.orchard_saks,
#[cfg(zcash_unstable = "nsm")]
burn_amount: self.burn_amount,

Check warning on line 411 in zcash_primitives/src/transaction/builder.rs

View check run for this annotation

Codecov / codecov/patch

zcash_primitives/src/transaction/builder.rs#L411

Added line #L411 was not covered by tests
tze_builder: self.tze_builder,
progress_notifier,
}
Expand Down Expand Up @@ -524,6 +533,11 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder<
.map_err(|_| BalanceError::Overflow)
},
)?,
#[cfg(zcash_unstable = "nsm")]
-self
.burn_amount
.map(Into::into)
.unwrap_or(ZatBalance::zero()),

Check warning on line 540 in zcash_primitives/src/transaction/builder.rs

View check run for this annotation

Codecov / codecov/patch

zcash_primitives/src/transaction/builder.rs#L536-L540

Added lines #L536 - L540 were not covered by tests
#[cfg(zcash_unstable = "zfuture")]
self.tze_builder.value_balance()?,
];
Expand Down Expand Up @@ -631,6 +645,11 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder<
.map_err(FeeError::FeeRule)
}

#[cfg(zcash_unstable = "nsm")]
pub fn set_burn_amount(&mut self, burn_amount: Option<NonNegativeAmount>) {
self.burn_amount = burn_amount;

Check warning on line 650 in zcash_primitives/src/transaction/builder.rs

View check run for this annotation

Codecov / codecov/patch

zcash_primitives/src/transaction/builder.rs#L649-L650

Added lines #L649 - L650 were not covered by tests
}

/// Builds a transaction from the configured spends and outputs.
///
/// Upon success, returns a tuple containing the final transaction, and the
Expand Down Expand Up @@ -743,7 +762,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder<
None => (None, orchard::builder::BundleMetadata::empty()),
};

#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]
let (tze_bundle, tze_signers) = self.tze_builder.build();

let unauthed_tx: TransactionData<Unauthorized> = TransactionData {
Expand All @@ -755,7 +774,9 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder<
sprout_bundle: None,
sapling_bundle,
orchard_bundle,
#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "nsm")]
burn_amount: self.burn_amount,
#[cfg(zcash_unstable = "tze")]
tze_bundle,
};

Expand All @@ -773,7 +794,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder<
)
});

#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "tze")]
let tze_bundle = unauthed_tx
.tze_bundle
.clone()
Expand Down Expand Up @@ -823,7 +844,9 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder<
sprout_bundle: unauthed_tx.sprout_bundle,
sapling_bundle,
orchard_bundle,
#[cfg(zcash_unstable = "zfuture")]
#[cfg(zcash_unstable = "nsm")]
burn_amount: self.burn_amount,
#[cfg(zcash_unstable = "tze")]
tze_bundle,
};

Expand Down Expand Up @@ -978,6 +1001,8 @@ mod tests {
expiry_height: sapling_activation_height + DEFAULT_TX_EXPIRY_DELTA,
transparent_builder: TransparentBuilder::empty(),
sapling_builder: None,
#[cfg(zcash_unstable = "nsm")]
burn_amount: None,
#[cfg(zcash_unstable = "zfuture")]
tze_builder: TzeBuilder::empty(),
#[cfg(not(zcash_unstable = "zfuture"))]
Expand Down Expand Up @@ -1139,6 +1164,24 @@ mod tests {
);
}

// Fail if there is only a burn
// 0.0005 burned, 0.0001 t-ZEC fee
#[cfg(zcash_unstable = "nsm")]
{
let build_config = BuildConfig::Standard {
sapling_anchor: Some(sapling::Anchor::empty_tree()),
orchard_anchor: Some(orchard::Anchor::empty_tree()),
};
let mut builder = Builder::new(TEST_NETWORK, tx_height, build_config);
builder.set_burn_amount(Some(NonNegativeAmount::const_from_u64(50000)));

assert_matches!(
builder.mock_build(OsRng),
Err(Error::InsufficientFunds(expected)) if expected ==
(NonNegativeAmount::const_from_u64(50000) + MINIMUM_FEE).unwrap().into()
);
}

let note1 = to.create_note(
sapling::value::NoteValue::from_raw(59999),
Rseed::BeforeZip212(jubjub::Fr::random(&mut rng)),
Expand Down Expand Up @@ -1179,6 +1222,40 @@ mod tests {
);
}

// Fail if there is insufficient input
// 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.0001 burned, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in
#[cfg(zcash_unstable = "nsm")]
{
let build_config = BuildConfig::Standard {
sapling_anchor: Some(witness1.root().into()),
orchard_anchor: Some(orchard::Anchor::empty_tree()),
};
let mut builder = Builder::new(TEST_NETWORK, tx_height, build_config);
builder
.add_sapling_spend::<Infallible>(&extsk, note1.clone(), witness1.path().unwrap())
.unwrap();
builder
.add_sapling_output::<Infallible>(
ovk,
to,
NonNegativeAmount::const_from_u64(30000),
MemoBytes::empty(),
)
.unwrap();
builder
.add_transparent_output(
&TransparentAddress::PublicKeyHash([0; 20]),
NonNegativeAmount::const_from_u64(10000),
)
.unwrap();
#[cfg(zcash_unstable = "nsm")]
builder.set_burn_amount(Some(NonNegativeAmount::const_from_u64(10000)));
assert_matches!(
builder.mock_build(OsRng),
Err(Error::InsufficientFunds(expected)) if expected == Amount::const_from_i64(1)
);
}

let note2 = to.create_note(
sapling::value::NoteValue::from_raw(1),
Rseed::BeforeZip212(jubjub::Fr::random(&mut rng)),
Expand Down Expand Up @@ -1221,5 +1298,47 @@ mod tests {
Ok(res) if res.transaction().fee_paid(|_| Err(BalanceError::Overflow)).unwrap() == Amount::const_from_i64(10_000)
);
}

// Succeeds if there is sufficient input
// 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.0001 t-ZEC fee, 0.0006 z-ZEC in
#[cfg(zcash_unstable = "nsm")]
{
let note1 = to.create_note(
sapling::value::NoteValue::from_raw(70000),
Rseed::BeforeZip212(jubjub::Fr::random(&mut rng)),
);
let cmu1 = Node::from_cmu(&note1.cmu());
let mut tree = CommitmentTree::<Node, 32>::empty();
tree.append(cmu1).unwrap();
let witness1 = IncrementalWitness::from_tree(tree.clone());

let build_config = BuildConfig::Standard {
sapling_anchor: Some(witness1.root().into()),
orchard_anchor: Some(orchard::Anchor::empty_tree()),
};
let mut builder = Builder::new(TEST_NETWORK, tx_height, build_config);
builder
.add_sapling_spend::<Infallible>(&extsk, note1, witness1.path().unwrap())
.unwrap();
builder
.add_sapling_output::<Infallible>(
ovk,
to,
NonNegativeAmount::const_from_u64(30000),
MemoBytes::empty(),
)
.unwrap();
builder
.add_transparent_output(
&TransparentAddress::PublicKeyHash([0; 20]),
NonNegativeAmount::const_from_u64(20000),
)
.unwrap();
builder.set_burn_amount(Some(NonNegativeAmount::const_from_u64(10000)));
assert_matches!(
builder.mock_build(OsRng),
Ok(res) if res.transaction().fee_paid(|_| Err(BalanceError::Overflow)).unwrap() == Amount::const_from_i64(10_000)
);
}
}
}
Loading

0 comments on commit 0ac99f7

Please sign in to comment.