[zk-token-sdk](docs) Update docs to include a brief description of how fee sigma proof is computed (#32288)
* function docs to focus on the action they perform * update docs for fee sigma proof * add link to zk token proof doc * Apply suggestions from code review Co-authored-by: Tyera <tyera@solana.com> --------- Co-authored-by: Tyera <tyera@solana.com>
This commit is contained in:
parent
4bc8f90182
commit
5624aaa1e5
|
@ -41,7 +41,7 @@ pub struct BatchedGroupedCiphertext2HandlesValidityProof(GroupedCiphertext2Handl
|
|||
#[allow(non_snake_case)]
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
impl BatchedGroupedCiphertext2HandlesValidityProof {
|
||||
/// Batched grouped ciphertext validity proof constructor.
|
||||
/// Creates a batched grouped ciphertext validity proof.
|
||||
///
|
||||
/// The function simply batches the input openings and invokes the standard grouped ciphertext
|
||||
/// validity proof constructor.
|
||||
|
@ -66,7 +66,7 @@ impl BatchedGroupedCiphertext2HandlesValidityProof {
|
|||
))
|
||||
}
|
||||
|
||||
/// Batched grouped ciphertext validity proof verifier.
|
||||
/// Verifies a batched grouped ciphertext validity proof.
|
||||
///
|
||||
/// The function does *not* hash the public keys, commitment, or decryption handles into the
|
||||
/// transcript. For security, the caller (the main protocol) should hash these public
|
||||
|
|
|
@ -45,7 +45,7 @@ pub struct CiphertextCiphertextEqualityProof {
|
|||
#[allow(non_snake_case)]
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
impl CiphertextCiphertextEqualityProof {
|
||||
/// The ciphertext-ciphertext equality proof constructor.
|
||||
/// Creates a ciphertext-ciphertext equality proof.
|
||||
///
|
||||
/// The function does *not* hash the public key, ciphertext, or commitment into the transcript.
|
||||
/// For security, the caller (the main protocol) should hash these public components prior to
|
||||
|
@ -120,8 +120,7 @@ impl CiphertextCiphertextEqualityProof {
|
|||
}
|
||||
}
|
||||
|
||||
/// The ciphertext-ciphertext equality proof verifier. The proof is with respect to two
|
||||
/// ciphertexts.
|
||||
/// Verifies a ciphertext-ciphertext equality proof.
|
||||
///
|
||||
/// * `source_pubkey` - The ElGamal pubkey associated with the first ciphertext to be proved
|
||||
/// * `destination_pubkey` - The ElGamal pubkey associated with the second ciphertext to be proved
|
||||
|
|
|
@ -49,7 +49,7 @@ pub struct CiphertextCommitmentEqualityProof {
|
|||
#[allow(non_snake_case)]
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
impl CiphertextCommitmentEqualityProof {
|
||||
/// Equality proof constructor. The proof is with respect to a ciphertext and commitment.
|
||||
/// Creates a ciphertext-commitment equality proof.
|
||||
///
|
||||
/// The function does *not* hash the public key, ciphertext, or commitment into the transcript.
|
||||
/// For security, the caller (the main protocol) should hash these public components prior to
|
||||
|
@ -120,7 +120,7 @@ impl CiphertextCommitmentEqualityProof {
|
|||
}
|
||||
}
|
||||
|
||||
/// Equality proof verifier. The proof is with respect to a single ciphertext and commitment.
|
||||
/// Verifies a ciphertext-commitment equality proof.
|
||||
///
|
||||
/// * `source_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved
|
||||
/// * `source_ciphertext` - The main ElGamal ciphertext to be proved
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
//! The sigma proofs for transfer fees.
|
||||
//! The fee sigma proof.
|
||||
//!
|
||||
//! TODO: Add detail on how the fee is calculated.
|
||||
//! A fee sigma proof certifies that an ElGamal ciphertext encrypts a properly computed transfer fee.
|
||||
//!
|
||||
//! A detailed description of how transfer fees and proofs are calculated is provided in the [`ZK
|
||||
//! Token proof program`] documentation.
|
||||
//!
|
||||
//! The protocol guarantees computational soundness (by the hardness of discrete log) and perfect
|
||||
//! zero-knowledge in the random oracle model.
|
||||
//!
|
||||
//! [`ZK Token proof program`]: https://edge.docs.solana.com/developing/runtime-facilities/zk-token-proof
|
||||
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
use {
|
||||
|
@ -27,9 +35,9 @@ use {
|
|||
/// Fee sigma proof.
|
||||
///
|
||||
/// The proof consists of two main components: `fee_max_proof` and `fee_equality_proof`. If the fee
|
||||
/// surpasses the maximum fee bound, then the `fee_max_proof` should properly be generated and
|
||||
/// `fee_equality_proof` should be simulated. If the fee is below the maximum fee bound, then the
|
||||
/// `fee_equality_proof` should be properly generated and `fee_max_proof` should be simulated.
|
||||
/// is greater than the maximum fee bound, then the `fee_max_proof` is properly generated and
|
||||
/// `fee_equality_proof` is simulated. If the fee is smaller than the maximum fee bound, the
|
||||
/// `fee_equality_proof` is properly generated and `fee_max_proof` is simulated.
|
||||
#[derive(Clone)]
|
||||
pub struct FeeSigmaProof {
|
||||
/// Proof that the committed fee amount equals the maximum fee bound
|
||||
|
@ -45,8 +53,36 @@ impl FeeSigmaProof {
|
|||
/// Creates a fee sigma proof assuming that the committed fee is greater than the maximum fee
|
||||
/// bound.
|
||||
///
|
||||
/// Note: the proof is generated twice via `create_proof_fee_above_max` and
|
||||
/// `create_proof_fee_below_max` to enforce constant time execution.
|
||||
/// A transfer fee amount `fee_amount` for a `transfer_amount` is determined by two parameters:
|
||||
/// - the `fee_rate_basis_point`, which defines the fee rate in units of 0.01%,
|
||||
/// - the `max_fee`, which defines the cap amount for a transfer fee.
|
||||
///
|
||||
/// This means that there are two cases to consider. If `fee_amount >= max_fee`, then the
|
||||
/// `fee_amount` must always equal `max_fee`.
|
||||
///
|
||||
/// If `fee_amount < max_fee`, then assuming that there is no division rounding, the
|
||||
/// `fee_amount` must satisfy the relation `transfer_amount * (fee_rate_basis_point /
|
||||
/// 10_000) = fee_amount` or equivalently, `(transfer_amount * fee_rate_basis_point) - (10_000
|
||||
/// * fee_amount) = 0`. More generally, let `delta_fee = (transfer_amount *
|
||||
/// fee_rate_basis_point) - (10_000 * fee_amount)`. Then assuming that a division rounding
|
||||
/// could occur, the `delta_fee` must satisfy the bound `0 <= delta_fee < 10_000`.
|
||||
///
|
||||
/// If `fee_amount >= max_fee`, then `fee_amount = max_fee` and therefore, the prover can
|
||||
/// generate a proof certifying that a fee commitment exactly encodes `max_fee`. If
|
||||
/// `fee_amount < max_fee`, then the prover can create a commitment to `delta_fee` and
|
||||
/// create a range proof certifying that the committed value satisfies the bound `0 <=
|
||||
/// delta_fee < 10_000`.
|
||||
///
|
||||
/// Since the type of proof that a prover generates reveals information about the transfer
|
||||
/// amount and transfer fee, the prover must generate and include both types of proof. If
|
||||
/// `fee_amount >= max_fee`, then the prover generates a valid `fee_max_proof`, but commits
|
||||
/// to 0 as the "claimed" delta value and simulates ("fakes") a proof (`fee_equality_proof`)
|
||||
/// that this is valid. If `fee_amount > max_fee`, then the prover simulates a
|
||||
/// `fee_max_proof`, and creates a valid `fee_equality_proof` certifying that the claimed delta
|
||||
/// value is equal to the "real" delta value.
|
||||
///
|
||||
/// Note: In the implementation, the proof is generated twice via `create_proof_fee_above_max`
|
||||
/// and `create_proof_fee_below_max` to enforce that the function executes in constant time.
|
||||
///
|
||||
/// * `(fee_amount, fee_commitment, fee_opening)` - The amount, Pedersen commitment, and
|
||||
/// opening of the transfer fee
|
||||
|
@ -85,7 +121,7 @@ impl FeeSigmaProof {
|
|||
let below_max = u64::ct_gt(&max_fee, &fee_amount);
|
||||
|
||||
// choose one of `proof_fee_above_max` or `proof_fee_below_max` according to whether the
|
||||
// fee amount surpasses max fee
|
||||
// fee amount is greater than `max_fee` or not
|
||||
let fee_max_proof = FeeMaxProof::conditional_select(
|
||||
&proof_fee_above_max.fee_max_proof,
|
||||
&proof_fee_below_max.fee_max_proof,
|
||||
|
@ -259,7 +295,7 @@ impl FeeSigmaProof {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fee sigma proof verifier.
|
||||
/// Verifies a fee sigma proof
|
||||
///
|
||||
/// * `fee_commitment` - The Pedersen commitment of the transfer fee
|
||||
/// * `delta_commitment` - The Pedersen commitment of the "real" delta value
|
||||
|
@ -443,6 +479,7 @@ impl ConditionallySelectable for FeeEqualityProof {
|
|||
}
|
||||
}
|
||||
|
||||
/// Selects one of two Ristretto points in constant time.
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
fn conditional_select_ristretto(
|
||||
a: &CompressedRistretto,
|
||||
|
|
|
@ -1,19 +1,9 @@
|
|||
//! Collection of sigma proofs (more precisely, "arguments") that are used in the Solana zk-token
|
||||
//! protocol.
|
||||
//! Collection of sigma proofs that are used in the ZK Token proof program.
|
||||
//!
|
||||
//! The module contains implementations of the following proof systems that work on Pedersen
|
||||
//! commitments and twisted ElGamal ciphertexts:
|
||||
//! - Equality proof: can be used to certify that a twisted ElGamal ciphertext encrypts the same
|
||||
//! message as either a Pedersen commitment or another ElGamal ciphertext.
|
||||
//! - Validity proof: can be used to certify that a twisted ElGamal ciphertext is a properly-formed
|
||||
//! ciphertext with respect to a pair of ElGamal public keys.
|
||||
//! - Zero-balance proof: can be used to certify that a twisted ElGamal ciphertext encrypts the
|
||||
//! message 0.
|
||||
//! - Fee proof: can be used to certify that an ElGamal ciphertext properly encrypts a transfer
|
||||
//! fee.
|
||||
//! Formal documentation and security proofs for the sigma proofs in this module can be found in
|
||||
//! [`ZK Token proof`] program documentation.
|
||||
//!
|
||||
//! We refer to the zk-token paper for the formal details and security proofs of these argument
|
||||
//! systems.
|
||||
//! [`ZK Token proof`]: https://edge.docs.solana.com/developing/runtime-facilities/zk-token-proof
|
||||
|
||||
pub mod batched_grouped_ciphertext_validity_proof;
|
||||
pub mod ciphertext_ciphertext_equality_proof;
|
||||
|
|
|
@ -41,7 +41,7 @@ pub struct PubkeyValidityProof {
|
|||
#[allow(non_snake_case)]
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
impl PubkeyValidityProof {
|
||||
/// Public-key proof constructor.
|
||||
/// Creates a public key validity proof.
|
||||
///
|
||||
/// The function does *not* hash the public key and ciphertext into the transcript. For
|
||||
/// security, the caller (the main protocol) should hash these public key components prior to
|
||||
|
@ -80,7 +80,7 @@ impl PubkeyValidityProof {
|
|||
Self { Y, z }
|
||||
}
|
||||
|
||||
/// Public-key proof verifier.
|
||||
/// Verifies a public key validity proof.
|
||||
///
|
||||
/// * `elgamal_pubkey` - The ElGamal public key to be proved
|
||||
/// * `transcript` - The transcript that does the bookkeeping for the Fiat-Shamir heuristic
|
||||
|
|
|
@ -41,7 +41,7 @@ pub struct ZeroBalanceProof {
|
|||
#[allow(non_snake_case)]
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
impl ZeroBalanceProof {
|
||||
/// Zero-balance proof constructor.
|
||||
/// Creates a zero-balance proof.
|
||||
///
|
||||
/// The function does *not* hash the public key and ciphertext into the transcript. For
|
||||
/// security, the caller (the main protocol) should hash these public components prior to
|
||||
|
@ -88,7 +88,7 @@ impl ZeroBalanceProof {
|
|||
Self { Y_P, Y_D, z }
|
||||
}
|
||||
|
||||
/// Zero-balance proof verifier.
|
||||
/// Verifies a zero-balance proof.
|
||||
///
|
||||
/// * `elgamal_pubkey` - The ElGamal pubkey associated with the ciphertext to be proved
|
||||
/// * `ciphertext` - The main ElGamal ciphertext to be proved
|
||||
|
|
Loading…
Reference in New Issue