zk-token-sdk: handle edge cases for transfer with fee (#23804)

* zk-token-sdk: handle edge cases for transfer with fee

* zk-token-sdk: clippy

* zk-token-sdk: clippy

* zk-token-sdk: cargo fmt
This commit is contained in:
samkim-crypto 2022-03-21 16:10:33 -04:00 committed by GitHub
parent cb06126388
commit 10eeafd3d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 244 additions and 115 deletions

View File

@ -6,6 +6,8 @@ use {
#[derive(Error, Clone, Debug, Eq, PartialEq)]
pub enum ProofError {
#[error("invalid transfer amount range")]
TransferAmount,
#[error("proof generation failed")]
Generation,
#[error("proof failed to verify")]

View File

@ -14,6 +14,7 @@ use {
errors::ProofError,
},
curve25519_dalek::scalar::Scalar,
subtle::ConstantTimeEq,
};
pub use {
close_account::CloseAccountData, transfer::TransferData,
@ -38,13 +39,22 @@ pub enum Role {
/// - the `bit_length` low bits of `amount` interpretted as u64
/// - the (64 - `bit_length`) high bits of `amount` interpretted as u64
#[cfg(not(target_arch = "bpf"))]
pub fn split_u64(amount: u64, bit_length: usize) -> (u64, u64) {
assert!(bit_length <= 64);
pub fn split_u64(
amount: u64,
lo_bit_length: usize,
hi_bit_length: usize,
) -> Result<(u64, u64), ProofError> {
assert!(lo_bit_length <= 64);
assert!(hi_bit_length <= 64);
let lo = amount << (64 - bit_length) >> (64 - bit_length);
let hi = amount >> bit_length;
if !bool::from((amount >> (lo_bit_length + hi_bit_length)).ct_eq(&0u64)) {
return Err(ProofError::TransferAmount);
}
(lo, hi)
let lo = amount << (64 - lo_bit_length) >> (64 - lo_bit_length);
let hi = amount >> lo_bit_length;
Ok((lo, hi))
}
#[cfg(not(target_arch = "bpf"))]

View File

@ -25,57 +25,18 @@ use {
};
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_SOURCE_AMOUNT_BIT_LENGTH: usize = 64;
const TRANSFER_SOURCE_AMOUNT_BITS: usize = 64;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_AMOUNT_LO_BIT_LENGTH: usize = 16;
const TRANSFER_AMOUNT_LO_BITS: usize = 16;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH: usize = 16;
const TRANSFER_AMOUNT_LO_NEGATED_BITS: usize = 16;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_AMOUNT_HI_BIT_LENGTH: usize = 32;
const TRANSFER_AMOUNT_HI_BITS: usize = 32;
#[cfg(not(target_arch = "bpf"))]
lazy_static::lazy_static! {
pub static ref COMMITMENT_MAX: PedersenCommitment = Pedersen::encode((1_u64 <<
TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH) - 1);
}
#[derive(Clone)]
#[repr(C)]
#[cfg(not(target_arch = "bpf"))]
pub struct TransferAmountEncryption {
pub commitment: PedersenCommitment,
pub source_handle: DecryptHandle,
pub destination_handle: DecryptHandle,
pub auditor_handle: DecryptHandle,
}
#[cfg(not(target_arch = "bpf"))]
impl TransferAmountEncryption {
pub fn new(
amount: u64,
source_pubkey: &ElGamalPubkey,
destination_pubkey: &ElGamalPubkey,
auditor_pubkey: &ElGamalPubkey,
) -> (Self, PedersenOpening) {
let (commitment, opening) = Pedersen::new(amount);
let transfer_amount_encryption = Self {
commitment,
source_handle: source_pubkey.decrypt_handle(&opening),
destination_handle: destination_pubkey.decrypt_handle(&opening),
auditor_handle: auditor_pubkey.decrypt_handle(&opening),
};
(transfer_amount_encryption, opening)
}
pub fn to_pod(&self) -> pod::TransferAmountEncryption {
pod::TransferAmountEncryption {
commitment: self.commitment.into(),
source_handle: self.source_handle.into(),
destination_handle: self.destination_handle.into(),
auditor_handle: self.auditor_handle.into(),
}
}
TRANSFER_AMOUNT_LO_NEGATED_BITS) - 1);
}
#[derive(Clone, Copy, Pod, Zeroable)]
@ -107,7 +68,11 @@ impl TransferData {
(destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
) -> Result<Self, ProofError> {
// split and encrypt transfer amount
let (amount_lo, amount_hi) = split_u64(transfer_amount, TRANSFER_AMOUNT_LO_BIT_LENGTH);
let (amount_lo, amount_hi) = split_u64(
transfer_amount,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_HI_BITS,
)?;
let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new(
amount_lo,
@ -142,7 +107,7 @@ impl TransferData {
- combine_lo_hi_ciphertexts(
&transfer_amount_lo_source,
&transfer_amount_hi_source,
TRANSFER_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_LO_BITS,
);
// generate transcript and append all public inputs
@ -222,7 +187,7 @@ impl TransferData {
let amount_hi = ciphertext_hi.decrypt_u32(sk);
if let (Some(amount_lo), Some(amount_hi)) = (amount_lo, amount_hi) {
let two_power = 1 << TRANSFER_AMOUNT_LO_BIT_LENGTH;
let two_power = 1 << TRANSFER_AMOUNT_LO_BITS;
Ok(amount_lo + two_power * amount_hi)
} else {
Err(ProofError::Decryption)
@ -336,7 +301,7 @@ impl TransferProof {
);
// generate the range proof
let range_proof = if TRANSFER_AMOUNT_LO_BIT_LENGTH == 32 {
let range_proof = if TRANSFER_AMOUNT_LO_BITS == 32 {
RangeProof::new(
vec![
source_new_balance,
@ -344,16 +309,16 @@ impl TransferProof {
transfer_amount_hi as u64,
],
vec![
TRANSFER_SOURCE_AMOUNT_BIT_LENGTH,
TRANSFER_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_HI_BIT_LENGTH,
TRANSFER_SOURCE_AMOUNT_BITS,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_HI_BITS,
],
vec![&source_opening, opening_lo, opening_hi],
transcript,
)
} else {
let transfer_amount_lo_negated =
(1 << TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH) - 1 - transfer_amount_lo as u64;
(1 << TRANSFER_AMOUNT_LO_NEGATED_BITS) - 1 - transfer_amount_lo as u64;
let opening_lo_negated = &PedersenOpening::default() - opening_lo;
RangeProof::new(
@ -364,10 +329,10 @@ impl TransferProof {
transfer_amount_hi as u64,
],
vec![
TRANSFER_SOURCE_AMOUNT_BIT_LENGTH,
TRANSFER_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH,
TRANSFER_AMOUNT_HI_BIT_LENGTH,
TRANSFER_SOURCE_AMOUNT_BITS,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_LO_NEGATED_BITS,
TRANSFER_AMOUNT_HI_BITS,
],
vec![&source_opening, opening_lo, &opening_lo_negated, opening_hi],
transcript,
@ -424,7 +389,7 @@ impl TransferProof {
// verify range proof
let new_source_commitment = self.new_source_commitment.try_into()?;
if TRANSFER_AMOUNT_LO_BIT_LENGTH == 32 {
if TRANSFER_AMOUNT_LO_BITS == 32 {
range_proof.verify(
vec![
&new_source_commitment,
@ -432,9 +397,9 @@ impl TransferProof {
&ciphertext_hi.commitment,
],
vec![
TRANSFER_SOURCE_AMOUNT_BIT_LENGTH,
TRANSFER_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_HI_BIT_LENGTH,
TRANSFER_SOURCE_AMOUNT_BITS,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_HI_BITS,
],
transcript,
)?;
@ -449,10 +414,10 @@ impl TransferProof {
&ciphertext_hi.commitment,
],
vec![
TRANSFER_SOURCE_AMOUNT_BIT_LENGTH,
TRANSFER_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH,
TRANSFER_AMOUNT_HI_BIT_LENGTH,
TRANSFER_SOURCE_AMOUNT_BITS,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_LO_NEGATED_BITS,
TRANSFER_AMOUNT_HI_BITS,
],
transcript,
)?;
@ -502,6 +467,45 @@ impl TransferPubkeys {
}
}
#[derive(Clone)]
#[repr(C)]
#[cfg(not(target_arch = "bpf"))]
pub struct TransferAmountEncryption {
pub commitment: PedersenCommitment,
pub source_handle: DecryptHandle,
pub destination_handle: DecryptHandle,
pub auditor_handle: DecryptHandle,
}
#[cfg(not(target_arch = "bpf"))]
impl TransferAmountEncryption {
pub fn new(
amount: u64,
source_pubkey: &ElGamalPubkey,
destination_pubkey: &ElGamalPubkey,
auditor_pubkey: &ElGamalPubkey,
) -> (Self, PedersenOpening) {
let (commitment, opening) = Pedersen::new(amount);
let transfer_amount_encryption = Self {
commitment,
source_handle: source_pubkey.decrypt_handle(&opening),
destination_handle: destination_pubkey.decrypt_handle(&opening),
auditor_handle: auditor_pubkey.decrypt_handle(&opening),
};
(transfer_amount_encryption, opening)
}
pub fn to_pod(&self) -> pod::TransferAmountEncryption {
pod::TransferAmountEncryption {
commitment: self.commitment.into(),
source_handle: self.source_handle.into(),
destination_handle: self.destination_handle.into(),
auditor_handle: self.auditor_handle.into(),
}
}
}
#[cfg(test)]
mod test {
use {super::*, crate::encryption::elgamal::ElGamalKeypair};
@ -513,6 +517,8 @@ mod test {
let dest_pk = ElGamalKeypair::new_rand().public;
let auditor_pk = ElGamalKeypair::new_rand().public;
// Case 1: transfer 0 amount
// create source account spendable ciphertext
let spendable_balance: u64 = 0;
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
@ -531,6 +537,29 @@ mod test {
assert!(transfer_data.verify().is_ok());
// Case 2: transfer max amount
// create source account spendable ciphertext
let spendable_balance: u64 = u64::max_value();
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
// transfer amount
let transfer_amount: u64 =
(1u64 << (TRANSFER_AMOUNT_LO_BITS + TRANSFER_AMOUNT_HI_BITS)) - 1;
// create transfer data
let transfer_data = TransferData::new(
transfer_amount,
(spendable_balance, &spendable_ciphertext),
&source_keypair,
(&dest_pk, &auditor_pk),
)
.unwrap();
assert!(transfer_data.verify().is_ok());
// Case 3: general success case
// create source account spendable ciphertext
let spendable_balance: u64 = 77;
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
@ -548,6 +577,25 @@ mod test {
.unwrap();
assert!(transfer_data.verify().is_ok());
// Case 4: transfer amount too big
// create source account spendable ciphertext
let spendable_balance: u64 = u64::max_value();
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
// transfer amount
let transfer_amount: u64 = 1u64 << (TRANSFER_AMOUNT_LO_BITS + TRANSFER_AMOUNT_HI_BITS);
// create transfer data
let transfer_data = TransferData::new(
transfer_amount,
(spendable_balance, &spendable_ciphertext),
&source_keypair,
(&dest_pk, &auditor_pk),
);
assert!(transfer_data.is_err());
}
#[test]

View File

@ -37,20 +37,20 @@ const MAX_FEE_BASIS_POINTS: u64 = 10_000;
const ONE_IN_BASIS_POINTS: u128 = MAX_FEE_BASIS_POINTS as u128;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_WITH_FEE_SOURCE_AMOUNT_BIT_LENGTH: usize = 64;
const TRANSFER_SOURCE_AMOUNT_BITS: usize = 64;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH: usize = 16;
const TRANSFER_AMOUNT_LO_BITS: usize = 16;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_WITH_FEE_AMOUNT_LO_NEGATED_BIT_LENGTH: usize = 16;
const TRANSFER_AMOUNT_LO_NEGATED_BITS: usize = 16;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_WITH_FEE_AMOUNT_HI_BIT_LENGTH: usize = 32;
const TRANSFER_AMOUNT_HI_BITS: usize = 32;
#[cfg(not(target_arch = "bpf"))]
const TRANSFER_WITH_FEE_DELTA_BIT_LENGTH: usize = 64;
const TRANSFER_DELTA_BITS: usize = 64;
#[cfg(not(target_arch = "bpf"))]
lazy_static::lazy_static! {
pub static ref COMMITMENT_MAX: PedersenCommitment = Pedersen::encode(1_u64 <<
TRANSFER_WITH_FEE_AMOUNT_LO_NEGATED_BIT_LENGTH);
pub static ref COMMITMENT_MAX: PedersenCommitment = Pedersen::encode((1_u64 <<
TRANSFER_AMOUNT_LO_NEGATED_BITS) - 1);
pub static ref COMMITMENT_MAX_FEE_BASIS_POINTS: PedersenCommitment = Pedersen::encode(MAX_FEE_BASIS_POINTS);
}
@ -91,8 +91,11 @@ impl TransferWithFeeData {
withdraw_withheld_authority_pubkey: &ElGamalPubkey,
) -> Result<Self, ProofError> {
// split and encrypt transfer amount
let (amount_lo, amount_hi) =
split_u64(transfer_amount, TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH);
let (amount_lo, amount_hi) = split_u64(
transfer_amount,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_HI_BITS,
)?;
let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new(
amount_lo,
@ -126,7 +129,7 @@ impl TransferWithFeeData {
- combine_lo_hi_ciphertexts(
&transfer_amount_lo_source,
&transfer_amount_hi_source,
TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH,
TRANSFER_AMOUNT_LO_BITS,
);
// calculate and encrypt fee
@ -229,7 +232,7 @@ impl TransferWithFeeData {
let amount_hi = ciphertext_hi.decrypt_u32(sk);
if let (Some(amount_lo), Some(amount_hi)) = (amount_lo, amount_hi) {
let two_power = 1 << TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH;
let two_power = 1 << TRANSFER_AMOUNT_LO_BITS;
Ok(amount_lo + two_power * amount_hi)
} else {
Err(ProofError::Verification)
@ -395,7 +398,7 @@ impl TransferWithFeeProof {
// generate the range proof
let opening_claimed_negated = &PedersenOpening::default() - &opening_claimed;
let range_proof = if TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH == 32 {
let range_proof = if TRANSFER_AMOUNT_LO_BITS == 32 {
RangeProof::new(
vec![
source_new_balance,
@ -405,11 +408,11 @@ impl TransferWithFeeProof {
MAX_FEE_BASIS_POINTS - delta_fee,
],
vec![
TRANSFER_WITH_FEE_SOURCE_AMOUNT_BIT_LENGTH,
TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH,
TRANSFER_WITH_FEE_AMOUNT_HI_BIT_LENGTH,
TRANSFER_WITH_FEE_DELTA_BIT_LENGTH,
TRANSFER_WITH_FEE_DELTA_BIT_LENGTH,
TRANSFER_SOURCE_AMOUNT_BITS,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_HI_BITS,
TRANSFER_DELTA_BITS,
TRANSFER_DELTA_BITS,
],
vec![
&opening_source,
@ -422,7 +425,7 @@ impl TransferWithFeeProof {
)
} else {
let transfer_amount_lo_negated =
(1 << TRANSFER_WITH_FEE_AMOUNT_LO_NEGATED_BIT_LENGTH) - transfer_amount_lo as u64;
((1 << TRANSFER_AMOUNT_LO_NEGATED_BITS) - 1) - transfer_amount_lo as u64;
let opening_lo_negated = &PedersenOpening::default() - opening_lo;
RangeProof::new(
@ -435,12 +438,12 @@ impl TransferWithFeeProof {
MAX_FEE_BASIS_POINTS - delta_fee,
],
vec![
TRANSFER_WITH_FEE_SOURCE_AMOUNT_BIT_LENGTH,
TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH,
TRANSFER_WITH_FEE_AMOUNT_LO_NEGATED_BIT_LENGTH,
TRANSFER_WITH_FEE_AMOUNT_HI_BIT_LENGTH,
TRANSFER_WITH_FEE_DELTA_BIT_LENGTH,
TRANSFER_WITH_FEE_DELTA_BIT_LENGTH,
TRANSFER_SOURCE_AMOUNT_BITS,
TRANSFER_AMOUNT_LO_BITS,
TRANSFER_AMOUNT_LO_NEGATED_BITS,
TRANSFER_AMOUNT_HI_BITS,
TRANSFER_DELTA_BITS,
TRANSFER_DELTA_BITS,
],
vec![
&opening_source,
@ -546,7 +549,7 @@ impl TransferWithFeeProof {
let new_source_commitment = self.new_source_commitment.try_into()?;
let claimed_commitment_negated = &(*COMMITMENT_MAX_FEE_BASIS_POINTS) - &claimed_commitment;
if TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH == 32 {
if TRANSFER_AMOUNT_LO_BITS == 32 {
range_proof.verify(
vec![
&new_source_commitment,
@ -695,13 +698,18 @@ impl FeeParameters {
fn calculate_fee(transfer_amount: u64, fee_rate_basis_points: u16) -> Option<(u64, u64)> {
let numerator = (transfer_amount as u128).checked_mul(fee_rate_basis_points as u128)?;
let mut fee = numerator.checked_div(ONE_IN_BASIS_POINTS)?;
let mut delta_fee = 0_u128;
let remainder = numerator.checked_rem(ONE_IN_BASIS_POINTS)?;
if remainder > 0 {
fee = fee.checked_add(1)?;
let scaled_fee = fee.checked_mul(ONE_IN_BASIS_POINTS)?;
delta_fee = scaled_fee.checked_sub(numerator)?;
}
let fee = u64::try_from(fee).ok()?;
Some((fee as u64, remainder as u64))
Some((fee as u64, delta_fee as u64))
}
#[cfg(not(target_arch = "bpf"))]
@ -714,18 +722,12 @@ fn compute_delta_commitment_and_opening(
let fee_rate_scalar = Scalar::from(fee_rate_basis_points);
let delta_commitment = fee_commitment * Scalar::from(MAX_FEE_BASIS_POINTS)
- &(&combine_lo_hi_commitments(
commitment_lo,
commitment_hi,
TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH,
) * &fee_rate_scalar);
- &(&combine_lo_hi_commitments(commitment_lo, commitment_hi, TRANSFER_AMOUNT_LO_BITS)
* &fee_rate_scalar);
let opening_delta = opening_fee * Scalar::from(MAX_FEE_BASIS_POINTS)
- &(&combine_lo_hi_openings(
opening_lo,
opening_hi,
TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH,
) * &fee_rate_scalar);
- &(&combine_lo_hi_openings(opening_lo, opening_hi, TRANSFER_AMOUNT_LO_BITS)
* &fee_rate_scalar);
(delta_commitment, opening_delta)
}
@ -740,11 +742,8 @@ fn compute_delta_commitment(
let fee_rate_scalar = Scalar::from(fee_rate_basis_points);
fee_commitment * Scalar::from(MAX_FEE_BASIS_POINTS)
- &(&combine_lo_hi_commitments(
commitment_lo,
commitment_hi,
TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH,
) * &fee_rate_scalar)
- &(&combine_lo_hi_commitments(commitment_lo, commitment_hi, TRANSFER_AMOUNT_LO_BITS)
* &fee_rate_scalar)
}
#[cfg(test)]
@ -758,6 +757,54 @@ mod test {
let auditor_pubkey = ElGamalKeypair::new_rand().public;
let withdraw_withheld_authority_pubkey = ElGamalKeypair::new_rand().public;
// Case 1: transfer 0 amount
let spendable_balance: u64 = 120;
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
let transfer_amount: u64 = 0;
let fee_parameters = FeeParameters {
fee_rate_basis_points: 400,
maximum_fee: 3,
};
let fee_data = TransferWithFeeData::new(
transfer_amount,
(spendable_balance, &spendable_ciphertext),
&source_keypair,
(&destination_pubkey, &auditor_pubkey),
fee_parameters,
&withdraw_withheld_authority_pubkey,
)
.unwrap();
assert!(fee_data.verify().is_ok());
// Case 2: transfer max amount
let spendable_balance: u64 = u64::max_value();
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
let transfer_amount: u64 =
(1u64 << (TRANSFER_AMOUNT_LO_BITS + TRANSFER_AMOUNT_HI_BITS)) - 1;
let fee_parameters = FeeParameters {
fee_rate_basis_points: 400,
maximum_fee: 3,
};
let fee_data = TransferWithFeeData::new(
transfer_amount,
(spendable_balance, &spendable_ciphertext),
&source_keypair,
(&destination_pubkey, &auditor_pubkey),
fee_parameters,
&withdraw_withheld_authority_pubkey,
)
.unwrap();
assert!(fee_data.verify().is_ok());
// Case 3: general success case
let spendable_balance: u64 = 120;
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
@ -779,5 +826,27 @@ mod test {
.unwrap();
assert!(fee_data.verify().is_ok());
// Case 4: transfer amount too big
let spendable_balance: u64 = u64::max_value();
let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance);
let transfer_amount: u64 = 1u64 << (TRANSFER_AMOUNT_LO_BITS + TRANSFER_AMOUNT_HI_BITS);
let fee_parameters = FeeParameters {
fee_rate_basis_points: 400,
maximum_fee: 3,
};
let fee_data = TransferWithFeeData::new(
transfer_amount,
(spendable_balance, &spendable_ciphertext),
&source_keypair,
(&destination_pubkey, &auditor_pubkey),
fee_parameters,
&withdraw_withheld_authority_pubkey,
);
assert!(fee_data.is_err());
}
}

View File

@ -494,12 +494,12 @@ mod test {
#[test]
fn test_fee_below_max_proof() {
let transfer_amount: u64 = 55;
let max_fee: u64 = 77;
let transfer_amount: u64 = 1;
let max_fee: u64 = 3;
let fee_rate: u16 = 555; // 5.55%
let fee_amount: u64 = 4;
let delta: u64 = 9475; // 4*10000 - 55*555
let fee_rate: u16 = 400; // 5.55%
let fee_amount: u64 = 1;
let delta: u64 = 9600; // 4*10000 - 55*555
let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
let (fee_commitment, fee_opening) = Pedersen::new(fee_amount);