diff --git a/zk-token-sdk/src/errors.rs b/zk-token-sdk/src/errors.rs index 78e79ac1ea..ac48999931 100644 --- a/zk-token-sdk/src/errors.rs +++ b/zk-token-sdk/src/errors.rs @@ -24,6 +24,8 @@ pub enum ProofError { "`zk_token_elgamal::pod::ElGamalCiphertext` contains invalid ElGamalCiphertext ciphertext" )] InconsistentCTData, + #[error("failed to decrypt ciphertext from transfer data")] + Decryption, } #[derive(Error, Clone, Debug, Eq, PartialEq)] diff --git a/zk-token-sdk/src/instruction/mod.rs b/zk-token-sdk/src/instruction/mod.rs index a0b0c5443f..f2b960b060 100644 --- a/zk-token-sdk/src/instruction/mod.rs +++ b/zk-token-sdk/src/instruction/mod.rs @@ -21,10 +21,6 @@ pub use { withdraw_withheld::WithdrawWithheldTokensData, }; -/// Constant for 2^32 -#[cfg(not(target_arch = "bpf"))] -const TWO_32: u64 = 4294967296; - #[cfg(not(target_arch = "bpf"))] pub trait Verifiable { fn verify(&self) -> Result<(), ProofError>; @@ -38,35 +34,45 @@ pub enum Role { Auditor, } -/// Split u64 number into two u32 numbers +/// Takes in a 64-bit number `amount` and a bit length `bit_length`. It returns: +/// - 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_into_u32(amount: u64) -> (u32, u32) { - let lo = amount as u32; - let hi = (amount >> 32) as u32; +pub fn split_u64(amount: u64, bit_length: usize) -> (u64, u64) { + assert!(bit_length <= 64); + + let lo = amount << (64 - bit_length) >> (64 - bit_length); + let hi = amount >> bit_length; (lo, hi) } #[cfg(not(target_arch = "bpf"))] -fn combine_u32_ciphertexts( +fn combine_lo_hi_ciphertexts( ciphertext_lo: &ElGamalCiphertext, ciphertext_hi: &ElGamalCiphertext, + bit_length: usize, ) -> ElGamalCiphertext { - ciphertext_lo + &(ciphertext_hi * &Scalar::from(TWO_32)) + let two_power = (1_u64) << bit_length; + ciphertext_lo + &(ciphertext_hi * &Scalar::from(two_power)) } #[cfg(not(target_arch = "bpf"))] -pub fn combine_u32_commitments( +pub fn combine_lo_hi_commitments( comm_lo: &PedersenCommitment, comm_hi: &PedersenCommitment, + bit_length: usize, ) -> PedersenCommitment { - comm_lo + comm_hi * &Scalar::from(TWO_32) + let two_power = (1_u64) << bit_length; + comm_lo + comm_hi * &Scalar::from(two_power) } #[cfg(not(target_arch = "bpf"))] -pub fn combine_u32_openings( +pub fn combine_lo_hi_openings( opening_lo: &PedersenOpening, opening_hi: &PedersenOpening, + bit_length: usize, ) -> PedersenOpening { - opening_lo + opening_hi * &Scalar::from(TWO_32) + let two_power = (1_u64) << bit_length; + opening_lo + opening_hi * &Scalar::from(two_power) } diff --git a/zk-token-sdk/src/instruction/transfer.rs b/zk-token-sdk/src/instruction/transfer.rs index 23cb4d42b9..7825211e08 100644 --- a/zk-token-sdk/src/instruction/transfer.rs +++ b/zk-token-sdk/src/instruction/transfer.rs @@ -12,7 +12,7 @@ use { pedersen::{Pedersen, PedersenCommitment, PedersenOpening}, }, errors::ProofError, - instruction::{combine_u32_ciphertexts, split_u64_into_u32, Role, Verifiable, TWO_32}, + instruction::{combine_lo_hi_ciphertexts, split_u64, Role, Verifiable}, range_proof::RangeProof, sigma_proofs::{ equality_proof::CtxtCommEqualityProof, validity_proof::AggregatedValidityProof, @@ -27,10 +27,18 @@ use { #[cfg(not(target_arch = "bpf"))] const TRANSFER_SOURCE_AMOUNT_BIT_LENGTH: usize = 64; #[cfg(not(target_arch = "bpf"))] -const TRANSFER_AMOUNT_LO_BIT_LENGTH: usize = 32; +const TRANSFER_AMOUNT_LO_BIT_LENGTH: usize = 16; +#[cfg(not(target_arch = "bpf"))] +const TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH: usize = 16; #[cfg(not(target_arch = "bpf"))] const TRANSFER_AMOUNT_HI_BIT_LENGTH: 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); +} + #[derive(Clone)] #[repr(C)] #[cfg(not(target_arch = "bpf"))] @@ -44,7 +52,7 @@ pub struct TransferAmountEncryption { #[cfg(not(target_arch = "bpf"))] impl TransferAmountEncryption { pub fn new( - amount: u32, + amount: u64, source_pubkey: &ElGamalPubkey, destination_pubkey: &ElGamalPubkey, auditor_pubkey: &ElGamalPubkey, @@ -99,7 +107,7 @@ impl TransferData { (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), ) -> Result { // split and encrypt transfer amount - let (amount_lo, amount_hi) = split_u64_into_u32(transfer_amount); + let (amount_lo, amount_hi) = split_u64(transfer_amount, TRANSFER_AMOUNT_LO_BIT_LENGTH); let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new( amount_lo, @@ -107,6 +115,7 @@ impl TransferData { destination_pubkey, auditor_pubkey, ); + let (ciphertext_hi, opening_hi) = TransferAmountEncryption::new( amount_hi, &source_keypair.public, @@ -130,7 +139,11 @@ impl TransferData { }; let new_source_ciphertext = ciphertext_old_source - - combine_u32_ciphertexts(&transfer_amount_lo_source, &transfer_amount_hi_source); + - combine_lo_hi_ciphertexts( + &transfer_amount_lo_source, + &transfer_amount_hi_source, + TRANSFER_AMOUNT_LO_BIT_LENGTH, + ); // generate transcript and append all public inputs let pod_transfer_pubkeys = pod::TransferPubkeys { @@ -201,11 +214,6 @@ impl TransferData { } /// Decrypts transfer amount from transfer data - /// - /// TODO: This function should run in constant time. Use `subtle::Choice` for the if statement - /// and make sure that the function does not terminate prematurely due to errors - /// - /// TODO: Define specific error type for decryption error pub fn decrypt_amount(&self, role: Role, sk: &ElGamalSecretKey) -> Result { let ciphertext_lo = self.ciphertext_lo(role)?; let ciphertext_hi = self.ciphertext_hi(role)?; @@ -214,9 +222,10 @@ impl TransferData { let amount_hi = ciphertext_hi.decrypt_u32(sk); if let (Some(amount_lo), Some(amount_hi)) = (amount_lo, amount_hi) { - Ok(amount_lo + TWO_32 * amount_hi) + let two_power = 1 << TRANSFER_AMOUNT_LO_BIT_LENGTH; + Ok(amount_lo + two_power * amount_hi) } else { - Err(ProofError::Verification) + Err(ProofError::Decryption) } } } @@ -252,7 +261,7 @@ impl Verifiable for TransferData { #[repr(C)] pub struct TransferProof { /// New Pedersen commitment for the remaining balance in source - pub commitment_new_source: pod::PedersenCommitment, + pub new_source_commitment: pod::PedersenCommitment, /// Associated equality proof pub equality_proof: pod::CtxtCommEqualityProof, @@ -295,7 +304,7 @@ impl TransferProof { } pub fn new( - (transfer_amount_lo, transfer_amount_hi): (u32, u32), + (transfer_amount_lo, transfer_amount_hi): (u64, u64), source_keypair: &ElGamalKeypair, (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), opening_lo: &PedersenOpening, @@ -304,10 +313,10 @@ impl TransferProof { transcript: &mut Transcript, ) -> Self { // generate a Pedersen commitment for the remaining balance in source - let (commitment_new_source, source_opening) = Pedersen::new(source_new_balance); + let (new_source_commitment, source_opening) = Pedersen::new(source_new_balance); - let pod_commitment_new_source: pod::PedersenCommitment = commitment_new_source.into(); - transcript.append_commitment(b"commitment-new-source", &pod_commitment_new_source); + let pod_new_source_commitment: pod::PedersenCommitment = new_source_commitment.into(); + transcript.append_commitment(b"commitment-new-source", &pod_new_source_commitment); // generate equality_proof let equality_proof = CtxtCommEqualityProof::new( @@ -327,23 +336,46 @@ impl TransferProof { ); // generate the range proof - let range_proof = RangeProof::new( - vec![ - source_new_balance, - transfer_amount_lo as u64, - transfer_amount_hi as u64, - ], - vec![ - TRANSFER_SOURCE_AMOUNT_BIT_LENGTH, - TRANSFER_AMOUNT_LO_BIT_LENGTH, - TRANSFER_AMOUNT_HI_BIT_LENGTH, - ], - vec![&source_opening, opening_lo, opening_hi], - transcript, - ); + let range_proof = if TRANSFER_AMOUNT_LO_BIT_LENGTH == 32 { + RangeProof::new( + vec![ + source_new_balance, + transfer_amount_lo as u64, + transfer_amount_hi as u64, + ], + vec![ + TRANSFER_SOURCE_AMOUNT_BIT_LENGTH, + TRANSFER_AMOUNT_LO_BIT_LENGTH, + TRANSFER_AMOUNT_HI_BIT_LENGTH, + ], + vec![&source_opening, opening_lo, opening_hi], + transcript, + ) + } else { + let transfer_amount_lo_negated = + (1 << TRANSFER_AMOUNT_LO_NEGATED_BIT_LENGTH) - transfer_amount_lo as u64; + let opening_lo_negated = &PedersenOpening::default() - opening_lo; + + RangeProof::new( + vec![ + source_new_balance, + transfer_amount_lo as u64, + transfer_amount_lo_negated, + 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, + ], + vec![&source_opening, opening_lo, &opening_lo_negated, opening_hi], + transcript, + ) + }; Self { - commitment_new_source: pod_commitment_new_source, + new_source_commitment: pod_new_source_commitment, equality_proof: equality_proof.into(), validity_proof: validity_proof.into(), range_proof: range_proof.try_into().expect("range proof: length error"), @@ -358,9 +390,9 @@ impl TransferProof { ciphertext_new_spendable: &ElGamalCiphertext, transcript: &mut Transcript, ) -> Result<(), ProofError> { - transcript.append_commitment(b"commitment-new-source", &self.commitment_new_source); + transcript.append_commitment(b"commitment-new-source", &self.new_source_commitment); - let commitment: PedersenCommitment = self.commitment_new_source.try_into()?; + let commitment: PedersenCommitment = self.new_source_commitment.try_into()?; let equality_proof: CtxtCommEqualityProof = self.equality_proof.try_into()?; let aggregated_validity_proof: AggregatedValidityProof = self.validity_proof.try_into()?; let range_proof: RangeProof = self.range_proof.try_into()?; @@ -391,16 +423,40 @@ impl TransferProof { )?; // verify range proof - let commitment_new_source = self.commitment_new_source.try_into()?; - range_proof.verify( - vec![ - &commitment_new_source, - &ciphertext_lo.commitment, - &ciphertext_hi.commitment, - ], - vec![64_usize, 32_usize, 32_usize], - transcript, - )?; + let new_source_commitment = self.new_source_commitment.try_into()?; + if TRANSFER_AMOUNT_LO_BIT_LENGTH == 32 { + range_proof.verify( + vec![ + &new_source_commitment, + &ciphertext_lo.commitment, + &ciphertext_hi.commitment, + ], + vec![ + TRANSFER_SOURCE_AMOUNT_BIT_LENGTH, + TRANSFER_AMOUNT_LO_BIT_LENGTH, + TRANSFER_AMOUNT_HI_BIT_LENGTH, + ], + transcript, + )?; + } else { + let commitment_lo_negated = &(*COMMITMENT_MAX) - &ciphertext_lo.commitment; + + range_proof.verify( + vec![ + &new_source_commitment, + &ciphertext_lo.commitment, + &commitment_lo_negated, + &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, + ], + transcript, + )?; + } Ok(()) } @@ -492,11 +548,11 @@ mod test { } = ElGamalKeypair::new_rand(); // create source account spendable ciphertext - let spendable_balance: u64 = 77; + let spendable_balance: u64 = 770000; let spendable_ciphertext = source_keypair.public.encrypt(spendable_balance); // transfer amount - let transfer_amount: u64 = 55; + let transfer_amount: u64 = 550000; // create transfer data let transfer_data = TransferData::new( @@ -511,19 +567,19 @@ mod test { transfer_data .decrypt_amount(Role::Source, &source_keypair.secret) .unwrap(), - 55_u64, + 550000_u64, ); assert_eq!( transfer_data.decrypt_amount(Role::Dest, &dest_sk).unwrap(), - 55_u64, + 550000_u64, ); assert_eq!( transfer_data .decrypt_amount(Role::Auditor, &auditor_sk) .unwrap(), - 55_u64, + 550000_u64, ); } } diff --git a/zk-token-sdk/src/instruction/transfer_with_fee.rs b/zk-token-sdk/src/instruction/transfer_with_fee.rs index feccc3f173..c66c2a1735 100644 --- a/zk-token-sdk/src/instruction/transfer_with_fee.rs +++ b/zk-token-sdk/src/instruction/transfer_with_fee.rs @@ -13,8 +13,8 @@ use { }, errors::ProofError, instruction::{ - combine_u32_ciphertexts, combine_u32_commitments, combine_u32_openings, - split_u64_into_u32, transfer::TransferAmountEncryption, Role, Verifiable, TWO_32, + combine_lo_hi_ciphertexts, combine_lo_hi_commitments, combine_lo_hi_openings, + split_u64, transfer::TransferAmountEncryption, Role, Verifiable, }, range_proof::RangeProof, sigma_proofs::{ @@ -39,7 +39,9 @@ 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; #[cfg(not(target_arch = "bpf"))] -const TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH: usize = 32; +const TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH: usize = 16; +#[cfg(not(target_arch = "bpf"))] +const TRANSFER_WITH_FEE_AMOUNT_LO_NEGATED_BIT_LENGTH: usize = 16; #[cfg(not(target_arch = "bpf"))] const TRANSFER_WITH_FEE_AMOUNT_HI_BIT_LENGTH: usize = 32; #[cfg(not(target_arch = "bpf"))] @@ -47,6 +49,8 @@ const TRANSFER_WITH_FEE_DELTA_BIT_LENGTH: 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_FEE_BASIS_POINTS: PedersenCommitment = Pedersen::encode(MAX_FEE_BASIS_POINTS); } @@ -87,7 +91,8 @@ impl TransferWithFeeData { withdraw_withheld_authority_pubkey: &ElGamalPubkey, ) -> Result { // split and encrypt transfer amount - let (amount_lo, amount_hi) = split_u64_into_u32(transfer_amount); + let (amount_lo, amount_hi) = + split_u64(transfer_amount, TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH); let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new( amount_lo, @@ -118,7 +123,11 @@ impl TransferWithFeeData { }; let new_source_ciphertext = old_source_ciphertext - - combine_u32_ciphertexts(&transfer_amount_lo_source, &transfer_amount_hi_source); + - combine_lo_hi_ciphertexts( + &transfer_amount_lo_source, + &transfer_amount_hi_source, + TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH, + ); // calculate and encrypt fee let (fee_amount, delta_fee) = @@ -212,11 +221,6 @@ impl TransferWithFeeData { } /// Decrypts transfer amount from transfer-with-fee data - /// - /// TODO: This function should run in constant time. Use `subtle::Choice` for the if statement - /// and make sure that the function does not terminate prematurely due to errors - /// - /// TODO: Define specific error type for decryption error pub fn decrypt_amount(&self, role: Role, sk: &ElGamalSecretKey) -> Result { let ciphertext_lo = self.ciphertext_lo(role)?; let ciphertext_hi = self.ciphertext_hi(role)?; @@ -225,7 +229,8 @@ impl TransferWithFeeData { let amount_hi = ciphertext_hi.decrypt_u32(sk); if let (Some(amount_lo), Some(amount_hi)) = (amount_lo, amount_hi) { - Ok(amount_lo + TWO_32 * amount_hi) + let two_power = 1 << TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH; + Ok(amount_lo + two_power * amount_hi) } else { Err(ProofError::Verification) } @@ -324,8 +329,8 @@ impl TransferWithFeeProof { #[allow(clippy::too_many_arguments)] #[allow(clippy::many_single_char_names)] pub fn new( - transfer_amount_lo_data: (u32, &TransferAmountEncryption, &PedersenOpening), - transfer_amount_hi_data: (u32, &TransferAmountEncryption, &PedersenOpening), + transfer_amount_lo_data: (u64, &TransferAmountEncryption, &PedersenOpening), + transfer_amount_hi_data: (u64, &TransferAmountEncryption, &PedersenOpening), source_keypair: &ElGamalKeypair, (destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey), (source_new_balance, new_source_ciphertext): (u64, &ElGamalCiphertext), @@ -388,31 +393,66 @@ impl TransferWithFeeProof { transcript, ); + // generate the range proof let opening_claimed_negated = &PedersenOpening::default() - &opening_claimed; - let range_proof = RangeProof::new( - vec![ - source_new_balance, - transfer_amount_lo as u64, - transfer_amount_hi as u64, - delta_fee, - 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, - ], - vec![ - &opening_source, - opening_lo, - opening_hi, - &opening_claimed, - &opening_claimed_negated, - ], - transcript, - ); + let range_proof = if TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH == 32 { + RangeProof::new( + vec![ + source_new_balance, + transfer_amount_lo as u64, + transfer_amount_hi as u64, + delta_fee, + 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, + ], + vec![ + &opening_source, + opening_lo, + opening_hi, + &opening_claimed, + &opening_claimed_negated, + ], + transcript, + ) + } else { + let transfer_amount_lo_negated = + (1 << TRANSFER_WITH_FEE_AMOUNT_LO_NEGATED_BIT_LENGTH) - transfer_amount_lo as u64; + let opening_lo_negated = &PedersenOpening::default() - opening_lo; + + RangeProof::new( + vec![ + source_new_balance, + transfer_amount_lo as u64, + transfer_amount_lo_negated, + transfer_amount_hi as u64, + delta_fee, + 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, + ], + vec![ + &opening_source, + opening_lo, + &opening_lo_negated, + opening_hi, + &opening_claimed, + &opening_claimed_negated, + ], + transcript, + ) + }; Self { new_source_commitment: pod_new_source_commitment, @@ -458,8 +498,6 @@ impl TransferWithFeeProof { transcript, )?; - println!("here"); - // verify that the transfer amount is encrypted correctly ciphertext_amount_validity_proof.verify( ( @@ -504,18 +542,38 @@ impl TransferWithFeeProof { transcript, )?; + // verify range proof + let new_source_commitment = self.new_source_commitment.try_into()?; let claimed_commitment_negated = &(*COMMITMENT_MAX_FEE_BASIS_POINTS) - &claimed_commitment; - range_proof.verify( - vec![ - &new_source_commitment, - &ciphertext_lo.commitment, - &ciphertext_hi.commitment, - &claimed_commitment, - &claimed_commitment_negated, - ], - vec![64, 32, 32, 64, 64], - transcript, - )?; + + if TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH == 32 { + range_proof.verify( + vec![ + &new_source_commitment, + &ciphertext_lo.commitment, + &ciphertext_hi.commitment, + &claimed_commitment, + &claimed_commitment_negated, + ], + vec![64, 32, 32, 64, 64], + transcript, + )?; + } else { + let commitment_lo_negated = &(*COMMITMENT_MAX) - &ciphertext_lo.commitment; + + range_proof.verify( + vec![ + &new_source_commitment, + &ciphertext_lo.commitment, + &commitment_lo_negated, + &ciphertext_hi.commitment, + &claimed_commitment, + &claimed_commitment_negated, + ], + vec![64, 16, 16, 32, 64, 64], + transcript, + )?; + } Ok(()) } @@ -656,10 +714,18 @@ 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_u32_commitments(commitment_lo, commitment_hi) * &fee_rate_scalar); + - &(&combine_lo_hi_commitments( + commitment_lo, + commitment_hi, + TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH, + ) * &fee_rate_scalar); let opening_delta = opening_fee * Scalar::from(MAX_FEE_BASIS_POINTS) - - &(&combine_u32_openings(opening_lo, opening_hi) * &fee_rate_scalar); + - &(&combine_lo_hi_openings( + opening_lo, + opening_hi, + TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH, + ) * &fee_rate_scalar); (delta_commitment, opening_delta) } @@ -674,7 +740,11 @@ fn compute_delta_commitment( let fee_rate_scalar = Scalar::from(fee_rate_basis_points); fee_commitment * Scalar::from(MAX_FEE_BASIS_POINTS) - - &(&combine_u32_commitments(commitment_lo, commitment_hi) * &fee_rate_scalar) + - &(&combine_lo_hi_commitments( + commitment_lo, + commitment_hi, + TRANSFER_WITH_FEE_AMOUNT_LO_BIT_LENGTH, + ) * &fee_rate_scalar) } #[cfg(test)]