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:
parent
043cc59c76
commit
736d11b45b
|
@ -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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]),
|
||||||
|
|
|
@ -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(¬e1.cmu());
|
let cm1 = Node::from_cmu(¬e1.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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(¬e1.cmu());
|
let cmu1 = Node::from_cmu(¬e1.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
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue