Change `transaction::fees::fixed::FeeRule::standard()` to use the ZIP 317

minimum fee (10000 zatoshis rather than 1000 zatoshis) as the fixed fee.

Signed-off-by: Daira Emma Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Emma Hopwood 2023-05-09 15:24:23 +01:00
parent 043cc59c76
commit 736d11b45b
6 changed files with 39 additions and 29 deletions

View File

@ -185,7 +185,7 @@ mod tests {
&Vec::<TxOut>::new(), &Vec::<TxOut>::new(),
&[TestSaplingInput { &[TestSaplingInput {
note_id: 0, note_id: 0,
value: Amount::from_u64(45000).unwrap(), value: Amount::from_u64(60000).unwrap(),
}], }],
&[SaplingPayment::new(Amount::from_u64(40000).unwrap())], &[SaplingPayment::new(Amount::from_u64(40000).unwrap())],
&DustOutputPolicy::default(), &DustOutputPolicy::default(),
@ -193,8 +193,8 @@ mod tests {
assert_matches!( assert_matches!(
result, result,
Ok(balance) if balance.proposed_change() == [ChangeValue::Sapling(Amount::from_u64(4000).unwrap())] Ok(balance) if balance.proposed_change() == [ChangeValue::Sapling(Amount::from_u64(10000).unwrap())]
&& balance.fee_required() == Amount::from_u64(1000).unwrap() && balance.fee_required() == Amount::from_u64(10000).unwrap()
); );
} }
@ -218,7 +218,7 @@ mod tests {
// enough to pay a fee, plus dust // enough to pay a fee, plus dust
TestSaplingInput { TestSaplingInput {
note_id: 0, note_id: 0,
value: Amount::from_u64(1100).unwrap(), value: Amount::from_u64(10100).unwrap(),
}, },
], ],
&[SaplingPayment::new(Amount::from_u64(40000).unwrap())], &[SaplingPayment::new(Amount::from_u64(40000).unwrap())],
@ -228,7 +228,7 @@ mod tests {
assert_matches!( assert_matches!(
result, result,
Err(ChangeError::InsufficientFunds { available, required }) Err(ChangeError::InsufficientFunds { available, required })
if available == Amount::from_u64(41100).unwrap() && required == Amount::from_u64(42000).unwrap() if available == Amount::from_u64(50100).unwrap() && required == Amount::from_u64(60000).unwrap()
); );
} }
} }

View File

@ -354,7 +354,7 @@ mod tests {
available, available,
required required
}) })
if available == Amount::zero() && required == Amount::from_u64(1001).unwrap() if available == Amount::zero() && required == Amount::from_u64(10001).unwrap()
); );
} }
@ -437,7 +437,7 @@ mod tests {
required required
}) })
if available == Amount::from_u64(50000).unwrap() if available == Amount::from_u64(50000).unwrap()
&& required == Amount::from_u64(71000).unwrap() && required == Amount::from_u64(80000).unwrap()
); );
// Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second // Mine blocks SAPLING_ACTIVATION_HEIGHT + 2 to 9 until just before the second
@ -472,7 +472,7 @@ mod tests {
required required
}) })
if available == Amount::from_u64(50000).unwrap() if available == Amount::from_u64(50000).unwrap()
&& required == Amount::from_u64(71000).unwrap() && required == Amount::from_u64(80000).unwrap()
); );
// Mine block 11 so that the second note becomes verified // Mine block 11 so that the second note becomes verified
@ -568,7 +568,7 @@ mod tests {
available, available,
required required
}) })
if available == Amount::zero() && required == Amount::from_u64(3000).unwrap() if available == Amount::zero() && required == Amount::from_u64(12000).unwrap()
); );
// Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds) // Mine blocks SAPLING_ACTIVATION_HEIGHT + 1 to 21 (that don't send us funds)
@ -602,7 +602,7 @@ mod tests {
available, available,
required required
}) })
if available == Amount::zero() && required == Amount::from_u64(3000).unwrap() if available == Amount::zero() && required == Amount::from_u64(12000).unwrap()
); );
// Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires // Mine block SAPLING_ACTIVATION_HEIGHT + 22 so that the first transaction expires
@ -752,7 +752,7 @@ mod tests {
let dfvk = usk.sapling().to_diversifiable_full_viewing_key(); let dfvk = usk.sapling().to_diversifiable_full_viewing_key();
// Add funds to the wallet in a single note // Add funds to the wallet in a single note
let value = Amount::from_u64(51000).unwrap(); let value = Amount::from_u64(60000).unwrap();
let (cb, _) = fake_compact_block( let (cb, _) = fake_compact_block(
sapling_activation_height(), sapling_activation_height(),
BlockHash([0; 32]), BlockHash([0; 32]),
@ -806,7 +806,7 @@ mod tests {
let dfvk = usk.sapling().to_diversifiable_full_viewing_key(); let dfvk = usk.sapling().to_diversifiable_full_viewing_key();
// Add funds to the wallet in a single note // Add funds to the wallet in a single note
let value = Amount::from_u64(51000).unwrap(); let value = Amount::from_u64(60000).unwrap();
let (cb, _) = fake_compact_block( let (cb, _) = fake_compact_block(
sapling_activation_height(), sapling_activation_height(),
BlockHash([0; 32]), BlockHash([0; 32]),

View File

@ -812,7 +812,7 @@ mod tests {
// create some inputs to spend // create some inputs to spend
let extsk = ExtendedSpendingKey::master(&[]); let extsk = ExtendedSpendingKey::master(&[]);
let to = extsk.default_address().1; let to = extsk.default_address().1;
let note1 = to.create_note(101000, Rseed::BeforeZip212(jubjub::Fr::random(&mut rng))); let note1 = to.create_note(110000, Rseed::BeforeZip212(jubjub::Fr::random(&mut rng)));
let cm1 = Node::from_cmu(&note1.cmu()); let cm1 = Node::from_cmu(&note1.cmu());
let mut tree = sapling::CommitmentTree::empty(); let mut tree = sapling::CommitmentTree::empty();
// fake that the note appears in some previous // fake that the note appears in some previous

View File

@ -78,6 +78,9 @@ and this library adheres to Rust's notion of
- `merkle_tree::incremental::read_auth_fragment_v1` - `merkle_tree::incremental::read_auth_fragment_v1`
- The depth of the `merkle_tree::{CommitmentTree, IncrementalWitness, and MerklePath}` - The depth of the `merkle_tree::{CommitmentTree, IncrementalWitness, and MerklePath}`
data types are now statically constrained using const generic type parameters. data types are now statically constrained using const generic type parameters.
- `transaction::fees::fixed::FeeRule::standard()` now uses the ZIP 317 minimum fee
(10000 zatoshis rather than 1000 zatoshis) as the fixed fee. To be compliant with
ZIP 317, use `transaction::fees::zip317::FeeRule::standard()` instead.
## [0.11.0] - 2023-04-15 ## [0.11.0] - 2023-04-15
### Added ### Added

View File

@ -550,7 +550,7 @@ mod tests {
memo::MemoBytes, memo::MemoBytes,
sapling::{Node, Rseed}, sapling::{Node, Rseed},
transaction::components::{ transaction::components::{
amount::{Amount, DEFAULT_FEE}, amount::Amount,
sapling::builder::{self as sapling_builder}, sapling::builder::{self as sapling_builder},
transparent::builder::{self as transparent_builder}, transparent::builder::{self as transparent_builder},
}, },
@ -646,7 +646,7 @@ mod tests {
builder builder
.add_transparent_output( .add_transparent_output(
&TransparentAddress::PublicKey([0; 20]), &TransparentAddress::PublicKey([0; 20]),
Amount::from_u64(49000).unwrap(), Amount::from_u64(40000).unwrap(),
) )
.unwrap(); .unwrap();
@ -682,7 +682,7 @@ mod tests {
builder builder
.add_transparent_output( .add_transparent_output(
&TransparentAddress::PublicKey([0; 20]), &TransparentAddress::PublicKey([0; 20]),
Amount::from_u64(49000).unwrap(), Amount::from_u64(40000).unwrap(),
) )
.unwrap(); .unwrap();
@ -711,6 +711,8 @@ mod tests {
#[test] #[test]
fn fails_on_negative_change() { fn fails_on_negative_change() {
use crate::transaction::fees::zip317::MINIMUM_FEE;
let mut rng = OsRng; let mut rng = OsRng;
// Just use the master key as the ExtendedSpendingKey for this test // Just use the master key as the ExtendedSpendingKey for this test
@ -725,7 +727,7 @@ mod tests {
let builder = Builder::new(TEST_NETWORK, tx_height); let builder = Builder::new(TEST_NETWORK, tx_height);
assert_eq!( assert_eq!(
builder.mock_build(), builder.mock_build(),
Err(Error::InsufficientFunds(DEFAULT_FEE)) Err(Error::InsufficientFunds(MINIMUM_FEE))
); );
} }
@ -734,7 +736,7 @@ mod tests {
let to = dfvk.default_address().1; let to = dfvk.default_address().1;
// Fail if there is only a Sapling output // Fail if there is only a Sapling output
// 0.0005 z-ZEC out, 0.00001 t-ZEC fee // 0.0005 z-ZEC out, 0.0001 t-ZEC fee
{ {
let mut builder = Builder::new(TEST_NETWORK, tx_height); let mut builder = Builder::new(TEST_NETWORK, tx_height);
builder builder
@ -748,13 +750,13 @@ mod tests {
assert_eq!( assert_eq!(
builder.mock_build(), builder.mock_build(),
Err(Error::InsufficientFunds( Err(Error::InsufficientFunds(
(Amount::from_i64(50000).unwrap() + DEFAULT_FEE).unwrap() (Amount::from_i64(50000).unwrap() + MINIMUM_FEE).unwrap()
)) ))
); );
} }
// Fail if there is only a transparent output // Fail if there is only a transparent output
// 0.0005 t-ZEC out, 0.00001 t-ZEC fee // 0.0005 t-ZEC out, 0.0001 t-ZEC fee
{ {
let mut builder = Builder::new(TEST_NETWORK, tx_height); let mut builder = Builder::new(TEST_NETWORK, tx_height);
builder builder
@ -766,19 +768,19 @@ mod tests {
assert_eq!( assert_eq!(
builder.mock_build(), builder.mock_build(),
Err(Error::InsufficientFunds( Err(Error::InsufficientFunds(
(Amount::from_i64(50000).unwrap() + DEFAULT_FEE).unwrap() (Amount::from_i64(50000).unwrap() + MINIMUM_FEE).unwrap()
)) ))
); );
} }
let note1 = to.create_note(50999, Rseed::BeforeZip212(jubjub::Fr::random(&mut rng))); let note1 = to.create_note(59999, Rseed::BeforeZip212(jubjub::Fr::random(&mut rng)));
let cmu1 = Node::from_cmu(&note1.cmu()); let cmu1 = Node::from_cmu(&note1.cmu());
let mut tree = CommitmentTree::<Node, 32>::empty(); let mut tree = CommitmentTree::<Node, 32>::empty();
tree.append(cmu1).unwrap(); tree.append(cmu1).unwrap();
let mut witness1 = IncrementalWitness::from_tree(tree.clone()); let mut witness1 = IncrementalWitness::from_tree(tree.clone());
// Fail if there is insufficient input // Fail if there is insufficient input
// 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.00001 t-ZEC fee, 0.00050999 z-ZEC in // 0.0003 z-ZEC out, 0.0002 t-ZEC out, 0.0001 t-ZEC fee, 0.00059999 z-ZEC in
{ {
let mut builder = Builder::new(TEST_NETWORK, tx_height); let mut builder = Builder::new(TEST_NETWORK, tx_height);
builder builder

View File

@ -1,9 +1,7 @@
use crate::{ use crate::{
consensus::{self, BlockHeight}, consensus::{self, BlockHeight},
transaction::components::{ transaction::components::{amount::Amount, transparent::fees as transparent},
amount::{Amount, DEFAULT_FEE}, transaction::fees::zip317,
transparent::fees as transparent,
},
}; };
#[cfg(feature = "zfuture")] #[cfg(feature = "zfuture")]
@ -22,10 +20,17 @@ impl FeeRule {
Self { fixed_fee } Self { fixed_fee }
} }
/// Creates a new fixed fee rule with the standard default fee. /// Creates a new fixed fee rule with the minimum possible [ZIP 317] fee,
/// i.e. 10000 zatoshis.
///
/// Note that using a fixed fee is not compliant with [ZIP 317]; consider
/// using [`zcash_primitives::transaction::fees::zip317::FeeRule`] instead.
///
/// [`zcash_primitives::transaction::fees::zip317::FeeRule`]: crate::transaction::fees::zip317::FeeRule
/// [ZIP 317]: https://zips.z.cash/zip-0317
pub fn standard() -> Self { pub fn standard() -> Self {
Self { Self {
fixed_fee: DEFAULT_FEE, fixed_fee: zip317::MINIMUM_FEE,
} }
} }