Skip to content

Commit

Permalink
[zk-token-sdk] Fix transfer with fee edge case error (solana-labs#34314)
Browse files Browse the repository at this point in the history
  • Loading branch information
samkim-crypto authored Dec 6, 2023
1 parent cf0c52c commit d21e7ed
Showing 1 changed file with 31 additions and 7 deletions.
38 changes: 31 additions & 7 deletions zk-token-sdk/src/instruction/transfer/with_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ use {
const MAX_FEE_BASIS_POINTS: u64 = 10_000;
#[cfg(not(target_os = "solana"))]
const ONE_IN_BASIS_POINTS: u128 = MAX_FEE_BASIS_POINTS as u128;
#[cfg(not(target_os = "solana"))]
const MAX_DELTA_RANGE: u64 = MAX_FEE_BASIS_POINTS - 1;

#[cfg(not(target_os = "solana"))]
const TRANSFER_SOURCE_AMOUNT_BITS: usize = 64;
Expand All @@ -51,7 +53,7 @@ const TRANSFER_AMOUNT_LO_NEGATED_BITS: usize = 16;
#[cfg(not(target_os = "solana"))]
const TRANSFER_AMOUNT_HI_BITS: usize = 32;
#[cfg(not(target_os = "solana"))]
const TRANSFER_DELTA_BITS: usize = 48;
const TRANSFER_DELTA_BITS: usize = 16;
#[cfg(not(target_os = "solana"))]
const FEE_AMOUNT_LO_BITS: usize = 16;
#[cfg(not(target_os = "solana"))]
Expand All @@ -62,6 +64,7 @@ lazy_static::lazy_static! {
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);
pub static ref COMMITMENT_MAX_DELTA_RANGE: PedersenCommitment = Pedersen::encode(MAX_DELTA_RANGE);
}

/// The instruction data that is needed for the `ProofInstruction::TransferWithFee` instruction.
Expand Down Expand Up @@ -557,24 +560,41 @@ impl TransferWithFeeProof {

// generate the range proof
let opening_claimed_negated = &PedersenOpening::default() - &opening_claimed;

let combined_amount = combine_lo_hi_u64(
transfer_amount_lo,
transfer_amount_hi,
TRANSFER_AMOUNT_LO_BITS,
);
let amount_sub_fee = combined_amount
.checked_sub(combined_fee_amount)
.ok_or(ProofGenerationError::FeeCalculation)?;
let amount_sub_fee_opening = combined_opening - combined_fee_opening;

let delta_negated = MAX_DELTA_RANGE
.checked_sub(delta_fee)
.ok_or(ProofGenerationError::FeeCalculation)?;

let range_proof = RangeProof::new(
vec![
source_new_balance,
transfer_amount_lo,
transfer_amount_hi,
delta_fee,
MAX_FEE_BASIS_POINTS - delta_fee,
delta_negated,
fee_amount_lo,
fee_amount_hi,
amount_sub_fee,
],
vec![
TRANSFER_SOURCE_AMOUNT_BITS, // 64
TRANSFER_AMOUNT_LO_BITS, // 16
TRANSFER_AMOUNT_HI_BITS, // 32
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 16
TRANSFER_DELTA_BITS, // 16
FEE_AMOUNT_LO_BITS, // 16
FEE_AMOUNT_HI_BITS, // 32
TRANSFER_SOURCE_AMOUNT_BITS, // 64
],
vec![
&opening_source,
Expand All @@ -584,6 +604,7 @@ impl TransferWithFeeProof {
&opening_claimed_negated,
opening_fee_lo,
opening_fee_hi,
&amount_sub_fee_opening,
],
transcript,
)?;
Expand Down Expand Up @@ -708,7 +729,8 @@ impl TransferWithFeeProof {

// verify range proof
let new_source_commitment = self.new_source_commitment.try_into()?;
let claimed_commitment_negated = &(*COMMITMENT_MAX_FEE_BASIS_POINTS) - &claimed_commitment;
let claimed_commitment_negated = &(*COMMITMENT_MAX_DELTA_RANGE) - &claimed_commitment;
let amount_sub_fee_commitment = combined_commitment - combined_fee_commitment;

range_proof.verify(
vec![
Expand All @@ -719,15 +741,17 @@ impl TransferWithFeeProof {
&claimed_commitment_negated,
fee_ciphertext_lo.get_commitment(),
fee_ciphertext_hi.get_commitment(),
&amount_sub_fee_commitment,
],
vec![
TRANSFER_SOURCE_AMOUNT_BITS, // 64
TRANSFER_AMOUNT_LO_BITS, // 16
TRANSFER_AMOUNT_HI_BITS, // 32
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 48
TRANSFER_DELTA_BITS, // 16
TRANSFER_DELTA_BITS, // 16
FEE_AMOUNT_LO_BITS, // 16
FEE_AMOUNT_HI_BITS, // 32
TRANSFER_SOURCE_AMOUNT_BITS, // 64
],
transcript,
)?;
Expand Down

0 comments on commit d21e7ed

Please sign in to comment.