From 6311409f4d0a716312def693e782857788f07b9b Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Fri, 6 Feb 2026 00:20:20 +0000 Subject: [PATCH 1/7] zksdk: upgrade to 5.0.0 --- .../fd_zksdk_ciphertext_ciphertext_equality.c | 41 ++++++++++++----- .../fd_zksdk_ciphertext_commitment_equality.c | 36 +++++++++++---- .../fd_zksdk_percentage_with_cap.c | 45 +++++++++++++------ .../instructions/fd_zksdk_pubkey_validity.c | 35 ++++++++++----- .../instructions/fd_zksdk_zero_ciphertext.c | 39 +++++++++++----- 5 files changed, 144 insertions(+), 52 deletions(-) diff --git a/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_ciphertext_equality.c b/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_ciphertext_equality.c index 42e00e25658..3ea951e81ef 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_ciphertext_equality.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_ciphertext_equality.c @@ -1,16 +1,19 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L263 */ static inline void -ciphertext_ciphertext_equality_transcript_init( fd_zksdk_transcript_t * transcript, - fd_zksdk_ciph_ciph_eq_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("ciphertext-ciphertext-equality-instruction") ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 ); - fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("first-ciphertext"), context->ciphertext1 ); - fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("second-ciphertext"), context->ciphertext2 ); +ciphertext_ciphertext_equality_hash_context( fd_zksdk_transcript_t * transcript, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + uchar const ciphertext1[ 64 ], + uchar const ciphertext2[ 64 ] ) { + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), pubkey1 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 ); + fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("first-ciphertext"), ciphertext1 ); + fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("second-ciphertext"), ciphertext2 ); } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L136 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L147 */ static inline int fd_zksdk_verify_proof_ciphertext_ciphertext_equality( fd_zksdk_ciph_ciph_eq_proof_t const * proof, @@ -44,6 +47,14 @@ fd_zksdk_verify_proof_ciphertext_ciphertext_equality( fd_ristretto255_point_t y0[1]; fd_ristretto255_point_t res[1]; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L158-L164 */ + if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext1[0], fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext1[32], fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zs )==NULL ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } @@ -88,7 +99,12 @@ fd_zksdk_verify_proof_ciphertext_ciphertext_equality( } /* Finalize transcript and extract challenges */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L166-L173 */ + ciphertext_ciphertext_equality_hash_context( transcript, pubkey1, pubkey2, ciphertext1, ciphertext2 ); fd_zksdk_transcript_domsep_ciph_ciph_eq_proof( transcript ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L185-L195 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); @@ -108,6 +124,8 @@ fd_zksdk_verify_proof_ciphertext_ciphertext_equality( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L196-L254 + Note: we use a slightly different MSM but they're equivalent. */ uchar ww[ 32 ]; fd_curve25519_scalar_mul( ww, w, w ); @@ -130,20 +148,21 @@ fd_zksdk_verify_proof_ciphertext_ciphertext_equality( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 11 ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L256-L260 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/ciphertext_ciphertext_equality.rs#L105 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/ciphertext_ciphertext_equality.rs#L122 */ int fd_zksdk_instr_verify_proof_ciphertext_ciphertext_equality( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("ciphertext-ciphertext-equality-instruction") ); + fd_zksdk_ciph_ciph_eq_context_t const * context = _context; fd_zksdk_ciph_ciph_eq_proof_t const * proof = _proof; - - ciphertext_ciphertext_equality_transcript_init( transcript, context ); return fd_zksdk_verify_proof_ciphertext_ciphertext_equality( proof, context->pubkey1, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c b/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c index b56e89d67b1..c646cfcd544 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c @@ -1,14 +1,17 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L229 */ static inline void -ciph_comm_eq_transcript_init( fd_zksdk_transcript_t * transcript, - fd_zksdk_ciph_comm_eq_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("ciphertext-commitment-equality-instruction") ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), context->pubkey ); - fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), context->ciphertext ); - fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("commitment"), context->commitment ); +ciph_comm_eq_hash_context( fd_zksdk_transcript_t * transcript, + uchar const pubkey [ 32 ], + uchar const ciphertext[ 64 ], + uchar const commitment[ 32 ] ) { + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), pubkey ); + fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), ciphertext ); + fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("commitment"), commitment ); } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L139 */ int fd_zksdk_verify_proof_ciphertext_commitment_equality( fd_zksdk_ciph_comm_eq_proof_t const * proof, @@ -46,6 +49,14 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( fd_ristretto255_point_t y2[1]; fd_ristretto255_point_t res[1]; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L146-L152 */ + if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext[0], fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext[32], fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zs )==NULL ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } @@ -81,7 +92,12 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( } /* Finalize transcript and extract challenges */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L154-L155 */ + ciph_comm_eq_hash_context( transcript, pubkey, ciphertext, commitment ); fd_zksdk_transcript_domsep_ciph_comm_eq_proof( transcript ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L158-L173 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); @@ -100,6 +116,9 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L174-L220 + Note: we use a slightly different MSM but they're equivalent. */ + /* Compute scalars */ fd_curve25519_scalar_neg( &scalars[ 7*32 ], c ); // -c fd_curve25519_scalar_mul( &scalars[ 6*32 ], proof->zs, w ); // z_s w @@ -113,6 +132,7 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 8 ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L222-L226 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y2 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } @@ -122,10 +142,10 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( int fd_zksdk_instr_verify_proof_ciphertext_commitment_equality( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("ciphertext-commitment-equality-instruction") ); + fd_zksdk_ciph_comm_eq_context_t const * context = _context; fd_zksdk_ciph_comm_eq_proof_t const * proof = _proof; - - ciph_comm_eq_transcript_init( transcript, context ); return fd_zksdk_verify_proof_ciphertext_commitment_equality( proof, context->pubkey, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c b/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c index 45b3ed7c28b..cf340df1fff 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c @@ -1,16 +1,19 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L522 */ static inline void -percentage_with_cap_transcript_init( fd_zksdk_transcript_t * transcript, - fd_zksdk_percentage_with_cap_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("percentage-with-cap-instruction") ); - fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("percentage-commitment"), context->percentage_commitment ); - fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("delta-commitment"), context->delta_commitment ); - fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("claimed-commitment"), context->claimed_commitment ); - fd_merlin_transcript_append_u64 ( transcript, FD_TRANSCRIPT_LITERAL("max-value"), context->max_value ); +percentage_with_cap_hash_context( fd_zksdk_transcript_t * transcript, + uchar const percentage_commitment[ 32 ], + uchar const delta_commitment [ 32 ], + uchar const claimed_commitment [ 32 ], + ulong max_value ) { + fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("percentage-commitment"), percentage_commitment ); + fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("delta-commitment"), delta_commitment ); + fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("claimed-commitment"), claimed_commitment ); + fd_merlin_transcript_append_u64 ( transcript, FD_TRANSCRIPT_LITERAL("max-value"), max_value ); } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L339 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L413 */ static inline int fd_zksdk_verify_proof_percentage_with_cap( fd_zksdk_percentage_with_cap_proof_t const * proof, @@ -40,6 +43,13 @@ fd_zksdk_verify_proof_percentage_with_cap( fd_ristretto255_point_t y[1]; fd_ristretto255_point_t res[1]; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L421-L426 */ + if( FD_UNLIKELY( fd_memeq( percentage_commitment, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( delta_commitment, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( claimed_commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->percentage_max_proof.z_max )==NULL ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } @@ -78,7 +88,15 @@ fd_zksdk_verify_proof_percentage_with_cap( } /* Finalize transcript and extract challenges */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L428-L435 */ + percentage_with_cap_hash_context( transcript, percentage_commitment, delta_commitment, claimed_commitment, max_value ); fd_zksdk_transcript_domsep_percentage_with_cap_proof( transcript ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L438-L481 */ + uchar m[ 32 ]; + fd_curve25519_scalar_from_u64( m, max_value ); + int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_max_proof"), proof->percentage_max_proof.y_max); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_delta"), proof->percentage_equality_proof.y_delta); @@ -99,10 +117,10 @@ fd_zksdk_verify_proof_percentage_with_cap( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L482-L513 + Note: we use a slightly different MSM but they're equivalent. */ uchar ww[ 32 ]; fd_curve25519_scalar_mul( ww, w, w ); - uchar m[ 32 ]; - fd_curve25519_scalar_from_u64( m, max_value ); uchar const * c_max = proof->percentage_max_proof.c_max; uchar * c_eq = c; @@ -131,20 +149,21 @@ fd_zksdk_verify_proof_percentage_with_cap( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 7 ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L515-L519 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/percentage_with_cap.rs#L118 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/percentage_with_cap.rs#L133 */ int fd_zksdk_instr_verify_proof_percentage_with_cap( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("percentage-with-cap-instruction") ); + fd_zksdk_percentage_with_cap_context_t const * context = _context; fd_zksdk_percentage_with_cap_proof_t const * proof = _proof; - - percentage_with_cap_transcript_init( transcript, context ); return fd_zksdk_verify_proof_percentage_with_cap( proof, context->percentage_commitment, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c index e8ec86f1d71..9abc1f9ab9e 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c @@ -1,13 +1,13 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L128 */ static inline void -pubkey_validity_transcript_init( fd_zksdk_transcript_t * transcript, - fd_zksdk_pubkey_validity_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("pubkey-validity-instruction") ); - fd_zksdk_transcript_append_pubkey( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), context->pubkey ); +pubkey_validity_hash_context( fd_zksdk_transcript_t * transcript, + uchar const pubkey[ 32 ] ) { + fd_zksdk_transcript_append_pubkey( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), pubkey ); } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L91 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L91 */ static inline int fd_zksdk_verify_proof_pubkey_validity( fd_zksdk_pubkey_validity_proof_t const * proof, @@ -26,6 +26,17 @@ fd_zksdk_verify_proof_pubkey_validity( fd_ristretto255_point_t y[1]; fd_ristretto255_point_t res[1]; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L96-L97 */ + pubkey_validity_hash_context( transcript, pubkey ); + fd_zksdk_transcript_domsep_pubkey_proof( transcript ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L102-L104 */ + if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + /* Validate scalar and decompress all points. + Note: Agave does this in various places, but any failure simply results in an invalid proof. */ if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->z )==NULL ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } @@ -38,8 +49,8 @@ fd_zksdk_verify_proof_pubkey_validity( return FD_ZKSDK_VERIFY_PROOF_ERROR; } - /* Finalize transcript and extract challenges */ - fd_zksdk_transcript_domsep_pubkey_proof( transcript ); + /* Finalize transcript and extract challenges + https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L107-L108 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y"), proof->y); if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { @@ -49,6 +60,9 @@ fd_zksdk_verify_proof_pubkey_validity( uchar c[ 32 ]; fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L111-L119 + Note: we use a slightly different MSM but they're equivalent. */ + /* Compute scalars */ fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->z ); // z fd_curve25519_scalar_neg( &scalars[ 1*32 ], c ); // -c @@ -56,20 +70,21 @@ fd_zksdk_verify_proof_pubkey_validity( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 2 ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L121-L125 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/pubkey_validity.rs#L73 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/pubkey_validity.rs#L73 */ int fd_zksdk_instr_verify_proof_pubkey_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("pubkey-validity-instruction") ); + fd_zksdk_pubkey_validity_context_t const * context = _context; fd_zksdk_pubkey_validity_proof_t const * proof = _proof; - - pubkey_validity_transcript_init( transcript, context ); return fd_zksdk_verify_proof_pubkey_validity( proof, context->pubkey, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c b/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c index 79f702f6d8a..491650b83f6 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c @@ -1,14 +1,15 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L166 */ static inline void -zero_ciphertext_transcript_init( fd_zksdk_transcript_t * transcript, - fd_zksdk_zero_ciphertext_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("zero-ciphertext-instruction") ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), context->pubkey ); - fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), context->ciphertext ); +zero_ciphertext_hash_context( fd_zksdk_transcript_t * transcript, + uchar const pubkey [ 32 ], + uchar const ciphertext[ 64 ] ) { + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), pubkey ); + fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), ciphertext ); } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L102 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L98 */ static inline int fd_zksdk_verify_proof_zero_ciphertext( fd_zksdk_zero_ciphertext_proof_t const * proof, @@ -35,12 +36,21 @@ fd_zksdk_verify_proof_zero_ciphertext( Y_P */ - /* Validate all inputs */ + /* Validate all inputs. */ uchar scalars[ 5 * 32 ]; fd_ristretto255_point_t points[5]; fd_ristretto255_point_t y[1]; fd_ristretto255_point_t res[1]; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L104-L108 + Reject identity pubkey and ciphertext.commitment. */ + if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext[0], fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + /* Validate scalar and decompress all points. + Note: Agave does this in various places, but any failure simply results in an invalid proof. */ if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->z )==NULL ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } @@ -63,7 +73,12 @@ fd_zksdk_verify_proof_zero_ciphertext( } /* Finalize transcript and extract challenges */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L110-L111 */ + zero_ciphertext_hash_context( transcript, pubkey, ciphertext ); fd_zksdk_transcript_domsep_zero_ciphertext_proof( transcript ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L118-L125 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_P"), proof->yp); if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { @@ -79,6 +94,9 @@ fd_zksdk_verify_proof_zero_ciphertext( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L140 + Note: we use a slightly different MSM but they're equivalent. */ + /* Compute scalars */ fd_curve25519_scalar_neg( &scalars[ 0*32 ], c ); // -c fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->z ); // z @@ -89,20 +107,21 @@ fd_zksdk_verify_proof_zero_ciphertext( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 5 ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L159-L163 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/zero_ciphertext.rs#L81 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/zero_ciphertext.rs#L88 */ int fd_zksdk_instr_verify_proof_zero_ciphertext( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("zero-ciphertext-instruction") ); + fd_zksdk_zero_ciphertext_context_t const * context = _context; fd_zksdk_zero_ciphertext_proof_t const * proof = _proof; - - zero_ciphertext_transcript_init( transcript, context ); return fd_zksdk_verify_proof_zero_ciphertext( proof, context->pubkey, From fe82665703f6e9c2f0a756f68b6f5a7fda9a93e1 Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Wed, 11 Feb 2026 17:50:47 +0000 Subject: [PATCH 2/7] zksdk: upgrade grp ciph 2 handles --- ...ed_grouped_ciphertext_2_handles_validity.c | 223 ++++------------ ...ksdk_batched_grouped_ciphertext_validity.h | 18 +- ...dk_grouped_ciphertext_2_handles_validity.c | 239 ++++++++++++++++-- ...dk_grouped_ciphertext_3_handles_validity.c | 6 +- .../instructions/fd_zksdk_zero_ciphertext.c | 5 +- 5 files changed, 276 insertions(+), 215 deletions(-) diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c index 45a4c6860e1..2c5a2218721 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c @@ -1,213 +1,76 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L163 */ static inline void -batched_grouped_ciphertext_validity_transcript_init( - fd_zksdk_transcript_t * transcript, - fd_zksdk_batched_grp_ciph_2h_val_context_t const * context ) { +batched_grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transcript, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + grp_ciph_2h_t const * grouped_ciphertext_lo, + grp_ciph_2h_t const * grouped_ciphertext_hi ) { fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-grouped-ciphertext-validity-2-handles-instruction") ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 ); - fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-lo"), (uchar *)&context->grouped_ciphertext_lo, sizeof(grp_ciph_2h_t) ); - fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)&context->grouped_ciphertext_hi, sizeof(grp_ciph_2h_t) ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), pubkey1 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 ); + fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-lo"), (uchar *)grouped_ciphertext_lo, sizeof(grp_ciph_2h_t) ); + fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)grouped_ciphertext_hi, sizeof(grp_ciph_2h_t) ); } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L106 */ int fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2h_val_proof_t const * proof, uchar const pubkey1 [ 32 ], uchar const pubkey2 [ 32 ], - uchar const comm [ 32 ], - uchar const handle1 [ 32 ], - uchar const handle2 [ 32 ], - uchar const comm_hi [ 32 ], - uchar const handle1_hi [ 32 ], - uchar const handle2_hi [ 32 ], - int const batched, + grp_ciph_2h_t const * grouped_ciphertext_lo, + grp_ciph_2h_t const * grouped_ciphertext_hi, fd_zksdk_transcript_t * transcript ) { - /* - We need to verify the 3 following equivalences. - Instead of verifying them one by one, it's more efficient to pack - them up in a single MSM (and to do so we have to mul by 1, w, w^2). - ( z_r H + z_x G =?= c C + Y_0 ) * 1 - ( z_r pub1 =?= c h1 + Y_1 ) * w - ( z_r pub2 =?= c h2 + Y_2 ) * w^2 - - When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi are NULL. - When batched==true, they are computed as C = C_lo + t C_hi. - - When pubkey2 is 0, also proof->y2, handle2 and handle2_hi should be 0. - - Because of batched and pubkey2_not_zero, the length of the MSM varies - between 6 and 12. - Points/scalars from 7 to 12 are only computed when required. - - We store points and scalars in the following arrays: - - points scalars - 0 G z_x - 1 H z_r - 2 Y_1 -w - 3 Y_2 -w^2 - 4 pub1 z_r w - 5 C -c - 6 h1 -c w - 7 C_hi -c t (if batched) - 8 h1_hi -c w t (if batched) - 9 pub2 z_r w^2 (if pubkey2_not_zero) - 10 h2 -c w^2 (if pubkey2_not_zero) - 11 h2_hi -c w^2 t (if batched && pubkey2_not_zero) - ----------------------- MSM - Y_0 - */ - - /* pubkey2 extra check: if pubkey2 is 0, then handle2, - handle2_hi (when set) and proof->y2 must all be 0. */ - int pubkey2_not_zero = 1; - if ( fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) ) { - pubkey2_not_zero = 0; - if ( - !fd_memeq( handle2, fd_ristretto255_compressed_zero, 32 ) - || !fd_memeq( proof->y2, fd_ristretto255_compressed_zero, 32 ) - || ( batched && !fd_memeq( handle2_hi, fd_ristretto255_compressed_zero, 32 ) ) - ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - } - - /* Validate all inputs */ - uchar scalars[ 12 * 32 ]; - fd_ristretto255_point_t points[12]; - fd_ristretto255_point_t y0[1]; - fd_ristretto255_point_t res[1]; - - if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) { + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L117-L122 */ + if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( grouped_ciphertext_lo->commitment, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( grouped_ciphertext_hi->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } - fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G ); - fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H ); - if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], proof->y1 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], proof->y2 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], pubkey1 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], comm )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], handle1 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - - ulong idx = 7; - if( batched ) { - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], comm_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle1_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - } - - if( pubkey2_not_zero ) { - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], pubkey2 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle2 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - } - - if( batched && pubkey2_not_zero ) { - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle2_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - } + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161-L166https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L124-L131 */ + batched_grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, grouped_ciphertext_lo, grouped_ciphertext_hi ); + fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 2 ); - /* Finalize transcript and extract challenges */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L133 */ uchar t[ 32 ]; - if( batched ) { - fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 2 ); - fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") ); - } + fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") ); - fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 2 ); - int val = FD_TRANSCRIPT_SUCCESS; - val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); - val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); - if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - /* Y_2 can be an all zero point if the pubkey2 is all zero */ - fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2); - - uchar c[ 32 ]; - uchar w[ 32 ]; - fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); - - fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_x"), proof->zx ); - fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_r"), proof->zr ); - - fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - - /* Compute scalars */ - fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx ); // z_x - fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr ); // z_r - fd_curve25519_scalar_neg( &scalars[ 2*32 ], w ); // -w - fd_curve25519_scalar_mul( &scalars[ 3*32 ], &scalars[ 2*32 ], w ); // -w^2 - fd_curve25519_scalar_mul( &scalars[ 4*32 ], proof->zr, w ); // z_r w - fd_curve25519_scalar_neg( &scalars[ 5*32 ], c ); // -c - fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 5*32 ], w ); // -c w - idx = 7; - if( batched ) { - fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 5*32 ], t ); // -c t - fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 6*32 ], t ); // -c w t - } - if( pubkey2_not_zero ) { - fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 4*32 ], w ); // z_r w^2 - fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 6*32 ], w ); // -c w^2 - } - if( batched && pubkey2_not_zero ) { - fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 8*32 ], w ); // -c w^2 t - } - - /* Compute the final MSM */ - fd_ristretto255_multi_scalar_mul( res, scalars, points, idx ); - - if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { - return FD_ZKSDK_VERIFY_PROOF_SUCCESS; - } - return FD_ZKSDK_VERIFY_PROOF_ERROR; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L135-L160 + Note: in our impl, t is embedded in the final MSM. */ + return fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( + proof, + pubkey1, + pubkey2, + grouped_ciphertext_lo->commitment, + grouped_ciphertext_lo->handles[0].handle, + grouped_ciphertext_lo->handles[1].handle, + grouped_ciphertext_hi->commitment, + grouped_ciphertext_hi->handles[0].handle, + grouped_ciphertext_hi->handles[1].handle, + t, + 1, + transcript + ); } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_2.rs#L126 */ int fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_2_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-grouped-ciphertext-validity-2-handles-instruction") ); + fd_zksdk_batched_grp_ciph_2h_val_context_t const * context = _context; fd_zksdk_batched_grp_ciph_2h_val_proof_t const * proof = _proof; - - batched_grouped_ciphertext_validity_transcript_init( transcript, context ); return fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( proof, context->pubkey1, context->pubkey2, - context->grouped_ciphertext_lo.commitment, - context->grouped_ciphertext_lo.handles[0].handle, - context->grouped_ciphertext_lo.handles[1].handle, - context->grouped_ciphertext_hi.commitment, - context->grouped_ciphertext_hi.handles[0].handle, - context->grouped_ciphertext_hi.handles[1].handle, - 1, + context->grouped_ciphertext_lo, + context->grouped_ciphertext_hi, transcript ); } diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h index a2cb0910cb6..795f27f0e99 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h @@ -41,35 +41,31 @@ typedef struct grp_ciph_handle grp_ciph_handle_t; struct __attribute__((packed)) grp_ciph_2h { uchar commitment [ 32 ]; // point - grp_ciph_handle_t handles [ 2 ]; // 2x points + grp_ciph_handle_t handles[ 2 ]; // 2x points }; typedef struct grp_ciph_2h grp_ciph_2h_t; struct __attribute__((packed)) grp_ciph_3h { uchar commitment [ 32 ]; // point - grp_ciph_handle_t handles [ 3 ]; // 3x points + grp_ciph_handle_t handles[ 3 ]; // 3x points }; typedef struct grp_ciph_3h grp_ciph_3h_t; - -/* https://github.com/anza-xyz/agave/blob/master/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_2.rs */ struct __attribute__((packed)) fd_zksdk_grp_ciph_2h_val_context { uchar pubkey1 [ 32 ]; // point uchar pubkey2 [ 32 ]; // point - grp_ciph_2h_t grouped_ciphertext; // 3x points + grp_ciph_2h_t grouped_ciphertext[1]; // 3x points }; typedef struct fd_zksdk_grp_ciph_2h_val_context fd_zksdk_grp_ciph_2h_val_context_t; -/* https://github.com/anza-xyz/agave/blob/master/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_2.rs#L47 */ struct __attribute__((packed)) fd_zksdk_batched_grp_ciph_2h_val_context { uchar pubkey1 [ 32 ]; // point uchar pubkey2 [ 32 ]; // point - grp_ciph_2h_t grouped_ciphertext_lo; // 3x points - grp_ciph_2h_t grouped_ciphertext_hi; // 3x points + grp_ciph_2h_t grouped_ciphertext_lo[1]; // 3x points + grp_ciph_2h_t grouped_ciphertext_hi[1]; // 3x points }; typedef struct fd_zksdk_batched_grp_ciph_2h_val_context fd_zksdk_batched_grp_ciph_2h_val_context_t; -/* https://github.com/anza-xyz/agave/blob/master/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_3.rs#L47 */ struct __attribute__((packed)) fd_zksdk_grp_ciph_3h_val_context { uchar pubkey1 [ 32 ]; // point uchar pubkey2 [ 32 ]; // point @@ -78,7 +74,6 @@ struct __attribute__((packed)) fd_zksdk_grp_ciph_3h_val_context { }; typedef struct fd_zksdk_grp_ciph_3h_val_context fd_zksdk_grp_ciph_3h_val_context_t; -/* https://github.com/anza-xyz/agave/blob/master/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_3.rs */ struct __attribute__((packed)) fd_zksdk_batched_grp_ciph_3h_val_context { uchar pubkey1 [ 32 ]; // point uchar pubkey2 [ 32 ]; // point @@ -89,7 +84,7 @@ struct __attribute__((packed)) fd_zksdk_batched_grp_ciph_3h_val_context { typedef struct fd_zksdk_batched_grp_ciph_3h_val_context fd_zksdk_batched_grp_ciph_3h_val_context_t; int -fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( +fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2h_val_proof_t const * proof, uchar const pubkey1 [ 32 ], uchar const pubkey2 [ 32 ], @@ -99,6 +94,7 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( uchar const comm_hi [ 32 ], uchar const handle1_hi [ 32 ], uchar const handle2_hi [ 32 ], + uchar const challenge_t[ 32 ], int const batched, fd_zksdk_transcript_t * transcript ); diff --git a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c index e7ad56a2f06..0d590d32d4a 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c @@ -1,34 +1,237 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161 */ static inline void -grouped_ciphertext_validity_transcript_init( - fd_zksdk_transcript_t * transcript, - fd_zksdk_grp_ciph_2h_val_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-validity-2-handles-instruction") ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 ); - fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)&context->grouped_ciphertext, sizeof(grp_ciph_2h_t) ); +grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transcript, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + grp_ciph_2h_t const * grouped_ciphertext ) { + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), pubkey1 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 ); + fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)grouped_ciphertext, sizeof(grp_ciph_2h_t) ); +} + +static inline int +fd_zksdk_verify_proof_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2h_val_proof_t const * proof, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + grp_ciph_2h_t const * grouped_ciphertext, + fd_zksdk_transcript_t * transcript ) { + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L155-L159 */ + if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( grouped_ciphertext->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161-L166 */ + grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, grouped_ciphertext ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L167 */ + return fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( + proof, + pubkey1, + pubkey2, + grouped_ciphertext->commitment, + grouped_ciphertext->handles[0].handle, + grouped_ciphertext->handles[1].handle, + NULL, + NULL, + NULL, + NULL, + 0, + transcript + ); +} + +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L170 + In Agave, the verify_direct() is a method of the NON-batched proof. + The batched proof is converted into a non-batched proof with 3 mul. + However, verify_direct() is doing a MSM so we can embed the 3 mul + as part of it. + So, in Firedancer verify_direct optionally supports a batched + proof and computes a single, adjusted MSM. */ +int +fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( + fd_zksdk_grp_ciph_2h_val_proof_t const * proof, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + uchar const comm [ 32 ], + uchar const handle1 [ 32 ], + uchar const handle2 [ 32 ], + uchar const comm_hi [ 32 ], + uchar const handle1_hi [ 32 ], + uchar const handle2_hi [ 32 ], + uchar const challenge_t[ 32 ], + int const batched, + fd_zksdk_transcript_t * transcript ) { + /* + We need to verify the 3 following equivalences. + Instead of verifying them one by one, it's more efficient to pack + them up in a single MSM (and to do so we have to mul by 1, w, w^2). + + ( z_r H + z_x G =?= c C + Y_0 ) * 1 + ( z_r pub1 =?= c h1 + Y_1 ) * w + ( z_r pub2 =?= c h2 + Y_2 ) * w^2 + + When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi are NULL. + When batched==true, they are computed as C = C_lo + t C_hi. + + When pubkey2 is 0, also proof->y2, handle2 and handle2_hi should be 0. + + Because of batched and pubkey2_not_zero, the length of the MSM varies + between 6 and 12. + Points/scalars from 7 to 12 are only computed when required. + + We store points and scalars in the following arrays: + + points scalars + 0 G z_x + 1 H z_r + 2 Y_1 -w + 3 Y_2 -w^2 + 4 pub1 z_r w + 5 C -c + 6 h1 -c w + 7 C_hi -c t (if batched) + 8 h1_hi -c w t (if batched) + 9 pub2 z_r w^2 (if pubkey2_not_zero) + 10 h2 -c w^2 (if pubkey2_not_zero) + 11 h2_hi -c w^2 t (if batched && pubkey2_not_zero) + ----------------------- MSM + Y_0 + */ + + /* Validate all inputs */ + uchar scalars[ 12 * 32 ]; + fd_ristretto255_point_t points[12]; + fd_ristretto255_point_t y0[1]; + fd_ristretto255_point_t res[1]; + + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G ); + fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H ); + if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], proof->y1 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], proof->y2 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], pubkey1 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], comm )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], handle1 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + ulong idx = 7; + if( batched ) { + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], comm_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle1_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + } + + int pubkey2_not_zero = !fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ); + if( pubkey2_not_zero ) { + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], pubkey2 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle2 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + } + + if( batched && pubkey2_not_zero ) { + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle2_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + } + + /* Finalize transcript and extract challenges */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L177 */ + fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 2 ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L179-L189 */ + int val = FD_TRANSCRIPT_SUCCESS; + val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); + val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); + if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + /* Y_2 can be an all zero point if the pubkey2 is all zero */ + fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2); + + uchar c[ 32 ]; + uchar w[ 32 ]; + fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); + + fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_x"), proof->zx ); + fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_r"), proof->zr ); + + fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L190-L244 + Note: we use a slightly different MSM but they're equivalent. */ + + /* Compute scalars */ + fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx ); // z_x + fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr ); // z_r + fd_curve25519_scalar_neg( &scalars[ 2*32 ], w ); // -w + fd_curve25519_scalar_mul( &scalars[ 3*32 ], &scalars[ 2*32 ], w ); // -w^2 + fd_curve25519_scalar_mul( &scalars[ 4*32 ], proof->zr, w ); // z_r w + fd_curve25519_scalar_neg( &scalars[ 5*32 ], c ); // -c + fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 5*32 ], w ); // -c w + idx = 7; + if( batched ) { + fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 5*32 ], challenge_t ); // -c t + fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 6*32 ], challenge_t ); // -c w t + } + if( pubkey2_not_zero ) { + fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 4*32 ], w ); // z_r w^2 + fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 6*32 ], w ); // -c w^2 + } + if( batched && pubkey2_not_zero ) { + fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 8*32 ], w ); // -c w^2 t + } + + /* Compute the final MSM */ + fd_ristretto255_multi_scalar_mul( res, scalars, points, idx ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L246-L250 */ + if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_SUCCESS; + } + return FD_ZKSDK_VERIFY_PROOF_ERROR; } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_2.rs#L109 */ int fd_zksdk_instr_verify_proof_grouped_ciphertext_2_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-validity-2-handles-instruction") ); + fd_zksdk_grp_ciph_2h_val_context_t const * context = _context; fd_zksdk_grp_ciph_2h_val_proof_t const * proof = _proof; - - grouped_ciphertext_validity_transcript_init( transcript, context ); - - return fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( + return fd_zksdk_verify_proof_grouped_ciphertext_2_handles_validity( proof, context->pubkey1, context->pubkey2, - context->grouped_ciphertext.commitment, - context->grouped_ciphertext.handles[0].handle, - context->grouped_ciphertext.handles[1].handle, - NULL, - NULL, - NULL, - 0, + context->grouped_ciphertext, transcript ); } diff --git a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c index 594b54fc586..3a601388999 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c @@ -4,7 +4,6 @@ static inline void grouped_ciphertext_validity_transcript_init( fd_zksdk_transcript_t * transcript, fd_zksdk_grp_ciph_3h_val_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-validity-3-handles-instruction") ); fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 ); fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 ); fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), context->pubkey3 ); @@ -14,11 +13,10 @@ grouped_ciphertext_validity_transcript_init( int fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-validity-3-handles-instruction") ); + fd_zksdk_grp_ciph_3h_val_context_t const * context = _context; fd_zksdk_grp_ciph_3h_val_proof_t const * proof = _proof; - - grouped_ciphertext_validity_transcript_init( transcript, context ); - return fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( proof, context->pubkey1, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c b/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c index 491650b83f6..79df6131129 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c @@ -44,8 +44,9 @@ fd_zksdk_verify_proof_zero_ciphertext( /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L104-L108 Reject identity pubkey and ciphertext.commitment. */ - if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) - || fd_memeq( &ciphertext[0], fd_ristretto255_compressed_zero, 32 ) ) ) { + if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext[0], fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( &ciphertext[32], fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } From f61f2f529d844a8b3e1d133ea5c4eb080176f32e Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Wed, 11 Feb 2026 22:09:33 +0000 Subject: [PATCH 3/7] zksdk: upgrade grp ciph 3 handles --- ...ed_grouped_ciphertext_2_handles_validity.c | 4 +- ...ed_grouped_ciphertext_3_handles_validity.c | 219 ++++------------ ...ksdk_batched_grouped_ciphertext_validity.h | 9 +- ...dk_grouped_ciphertext_2_handles_validity.c | 2 +- ...dk_grouped_ciphertext_3_handles_validity.c | 238 ++++++++++++++++-- .../fd_zksdk_percentage_with_cap.c | 2 +- 6 files changed, 281 insertions(+), 193 deletions(-) diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c index 2c5a2218721..1e892fa08e7 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c @@ -15,7 +15,7 @@ batched_grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transc } /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L106 */ -int +static inline int fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2h_val_proof_t const * proof, uchar const pubkey1 [ 32 ], @@ -31,7 +31,7 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( return FD_ZKSDK_VERIFY_PROOF_ERROR; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161-L166https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L124-L131 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L124-L131 */ batched_grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, grouped_ciphertext_lo, grouped_ciphertext_hi ); fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 2 ); diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c index 49ac2573718..47ef164e5a3 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c @@ -1,201 +1,84 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L180 */ static inline void -batched_grouped_ciphertext_validity_transcript_init( - fd_zksdk_transcript_t * transcript, - fd_zksdk_batched_grp_ciph_3h_val_context_t const * context ) { - fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-grouped-ciphertext-validity-3-handles-instruction") ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), context->pubkey3 ); - fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-lo"), (uchar *)&context->grouped_ciphertext_lo, sizeof(grp_ciph_3h_t) ); - fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)&context->grouped_ciphertext_hi, sizeof(grp_ciph_3h_t) ); +batched_grouped_ciphertext_validity_hash_context( + fd_zksdk_transcript_t * transcript, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + uchar const pubkey3 [ 32 ], + grp_ciph_3h_t const * grouped_ciphertext_lo, + grp_ciph_3h_t const * grouped_ciphertext_hi ) { + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), pubkey1 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), pubkey3 ); + fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-lo"), (uchar *)grouped_ciphertext_lo, sizeof(grp_ciph_3h_t) ); + fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)grouped_ciphertext_hi, sizeof(grp_ciph_3h_t) ); } -int +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L111 */ +static inline int fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( fd_zksdk_grp_ciph_3h_val_proof_t const * proof, uchar const pubkey1 [ 32 ], uchar const pubkey2 [ 32 ], uchar const pubkey3 [ 32 ], - uchar const comm [ 32 ], - uchar const handle1 [ 32 ], - uchar const handle2 [ 32 ], - uchar const handle3 [ 32 ], - uchar const comm_hi [ 32 ], - uchar const handle1_hi [ 32 ], - uchar const handle2_hi [ 32 ], - uchar const handle3_hi [ 32 ], - int const batched, + grp_ciph_3h_t const * grouped_ciphertext_lo, + grp_ciph_3h_t const * grouped_ciphertext_hi, fd_zksdk_transcript_t * transcript ) { - /* - When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi, h3_hi are NULL. - When batched==true, they are computed as C = C_lo + t C_hi. - - We store points and scalars in the following arrays: - - points scalars - 0 G z_x - 1 H z_r - 2 C -c - 3 pub1 w z_r - 4 Y_1 -w - 5 h1 -w c - 6 pub2 ww z_r - 7 Y_2 -ww - 8 h2 -ww c - 9 pub3 www z_r - 10 Y_3 -www - 11 h3 -www c - 12 C_hi -c t (if batched) - 13 h1_hi -c w t (if batched) - 14 h2_hi -c ww t (if batched) - 15 h3_hi -c www t (if batched) - ----------------------- MSM - Y_0 - */ - /* Validate all inputs */ - uchar scalars[ 16 * 32 ]; - fd_ristretto255_point_t points[16]; - fd_ristretto255_point_t y0[1]; - fd_ristretto255_point_t res[1]; - - if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - - fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G ); - fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H ); - if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], comm )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], pubkey1 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->y1 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], handle1 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], pubkey2 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], proof->y2 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[8], handle2 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[9], pubkey3 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[10], proof->y3 )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[11], handle3 )==NULL ) ) { + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L123-L129 */ + if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( grouped_ciphertext_lo->commitment, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( grouped_ciphertext_hi->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } - if (batched) { - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[12], comm_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[13], handle1_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[14], handle2_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[15], handle3_hi )==NULL ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - } + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L131-L139 */ + batched_grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, pubkey3, grouped_ciphertext_lo, grouped_ciphertext_hi ); + fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 3 ); - /* Finalize transcript and extract challenges */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L141 */ uchar t[ 32 ]; - if( batched ) { - fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 3 ); - fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") ); - } - - fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 3 ); - int val = FD_TRANSCRIPT_SUCCESS; - val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); - val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); - val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2); - if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { - return FD_ZKSDK_VERIFY_PROOF_ERROR; - } - /* Y_3 can be zero */ - fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_3"), proof->y3); - - uchar c[ 32 ]; - uchar w[ 32 ]; - fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); - - fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_x"), proof->zx ); - fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_r"), proof->zr ); - - fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") ); - /* Compute scalars */ - fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx ); // z_x - fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr ); // z_r - fd_curve25519_scalar_neg( &scalars[ 2*32 ], c ); // -c - fd_curve25519_scalar_mul( &scalars[ 3*32 ], proof->zr, w ); // w z_r - fd_curve25519_scalar_neg( &scalars[ 4*32 ], w ); // -w - fd_curve25519_scalar_mul( &scalars[ 5*32 ], &scalars[ 2*32 ], w ); // -w c - fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 3*32 ], w ); // ww z_r - fd_curve25519_scalar_mul( &scalars[ 7*32 ], &scalars[ 4*32 ], w ); // -ww - fd_curve25519_scalar_mul( &scalars[ 8*32 ], &scalars[ 5*32 ], w ); // -ww c - fd_curve25519_scalar_mul( &scalars[ 9*32 ], &scalars[ 6*32 ], w ); // www z_r - fd_curve25519_scalar_mul( &scalars[ 10*32 ], &scalars[ 7*32 ], w ); // -www - fd_curve25519_scalar_mul( &scalars[ 11*32 ], &scalars[ 8*32 ], w ); // -www c - if( batched ) { - fd_curve25519_scalar_mul( &scalars[ 12*32 ], &scalars[ 2*32 ], t ); // -c t - fd_curve25519_scalar_mul( &scalars[ 13*32 ], &scalars[ 5*32 ], t ); // -c w t - fd_curve25519_scalar_mul( &scalars[ 14*32 ], &scalars[ 8*32 ], t ); // -c ww t - fd_curve25519_scalar_mul( &scalars[ 15*32 ], &scalars[ 11*32 ], t ); // -c www t - } - - /* Compute the final MSM */ - fd_ristretto255_multi_scalar_mul( res, scalars, points, batched ? 16 : 12 ); - - if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { - return FD_ZKSDK_VERIFY_PROOF_SUCCESS; - } - return FD_ZKSDK_VERIFY_PROOF_ERROR; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L143-L177 + Note: in our impl, t is embedded in the final MSM. */ + return fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( + proof, + pubkey1, + pubkey2, + pubkey3, + grouped_ciphertext_lo->commitment, + grouped_ciphertext_lo->handles[0].handle, + grouped_ciphertext_lo->handles[1].handle, + grouped_ciphertext_lo->handles[2].handle, + grouped_ciphertext_hi->commitment, + grouped_ciphertext_hi->handles[0].handle, + grouped_ciphertext_hi->handles[1].handle, + grouped_ciphertext_hi->handles[2].handle, + t, + 1, + transcript + ); } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_3.rs#L138 */ int fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; + fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-grouped-ciphertext-validity-3-handles-instruction") ); + fd_zksdk_batched_grp_ciph_3h_val_context_t const * context = _context; fd_zksdk_batched_grp_ciph_3h_val_proof_t const * proof = _proof; - - batched_grouped_ciphertext_validity_transcript_init( transcript, context ); return fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( proof, context->pubkey1, context->pubkey2, context->pubkey3, - context->grouped_ciphertext_lo.commitment, - context->grouped_ciphertext_lo.handles[0].handle, - context->grouped_ciphertext_lo.handles[1].handle, - context->grouped_ciphertext_lo.handles[2].handle, - context->grouped_ciphertext_hi.commitment, - context->grouped_ciphertext_hi.handles[0].handle, - context->grouped_ciphertext_hi.handles[1].handle, - context->grouped_ciphertext_hi.handles[2].handle, - 1, + context->grouped_ciphertext_lo, + context->grouped_ciphertext_hi, transcript ); } diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h index 795f27f0e99..f9d0424b48a 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_validity.h @@ -70,7 +70,7 @@ struct __attribute__((packed)) fd_zksdk_grp_ciph_3h_val_context { uchar pubkey1 [ 32 ]; // point uchar pubkey2 [ 32 ]; // point uchar pubkey3 [ 32 ]; // point - grp_ciph_3h_t grouped_ciphertext; // 4x points + grp_ciph_3h_t grouped_ciphertext[1]; // 4x points }; typedef struct fd_zksdk_grp_ciph_3h_val_context fd_zksdk_grp_ciph_3h_val_context_t; @@ -78,8 +78,8 @@ struct __attribute__((packed)) fd_zksdk_batched_grp_ciph_3h_val_context { uchar pubkey1 [ 32 ]; // point uchar pubkey2 [ 32 ]; // point uchar pubkey3 [ 32 ]; // point - grp_ciph_3h_t grouped_ciphertext_lo; // 4x points - grp_ciph_3h_t grouped_ciphertext_hi; // 4x points + grp_ciph_3h_t grouped_ciphertext_lo[1]; // 4x points + grp_ciph_3h_t grouped_ciphertext_hi[1]; // 4x points }; typedef struct fd_zksdk_batched_grp_ciph_3h_val_context fd_zksdk_batched_grp_ciph_3h_val_context_t; @@ -99,7 +99,7 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( fd_zksdk_transcript_t * transcript ); int -fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( +fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( fd_zksdk_grp_ciph_3h_val_proof_t const * proof, uchar const pubkey1 [ 32 ], uchar const pubkey2 [ 32 ], @@ -112,6 +112,7 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( uchar const handle1_hi [ 32 ], uchar const handle2_hi [ 32 ], uchar const handle3_hi [ 32 ], + uchar const challenge_t[ 32 ], int const batched, fd_zksdk_transcript_t * transcript ); diff --git a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c index 0d590d32d4a..79e704b6794 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c @@ -185,7 +185,7 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L190-L244 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L190-L244 Note: we use a slightly different MSM but they're equivalent. */ /* Compute scalars */ diff --git a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c index 3a601388999..70c9d96033c 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c @@ -1,15 +1,227 @@ #include "../fd_zksdk_private.h" +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L299 */ static inline void -grouped_ciphertext_validity_transcript_init( - fd_zksdk_transcript_t * transcript, - fd_zksdk_grp_ciph_3h_val_context_t const * context ) { - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 ); - fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), context->pubkey3 ); - fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)&context->grouped_ciphertext, sizeof(grp_ciph_3h_t) ); +grouped_ciphertext_validity_hash_context( + fd_zksdk_transcript_t * transcript, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + uchar const pubkey3 [ 32 ], + grp_ciph_3h_t const * grouped_ciphertext ) { + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), pubkey1 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 ); + fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), pubkey3 ); + fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)grouped_ciphertext, sizeof(grp_ciph_3h_t) ); } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L163 */ +static inline int +fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity( + fd_zksdk_grp_ciph_3h_val_proof_t const * proof, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + uchar const pubkey3 [ 32 ], + grp_ciph_3h_t const * grouped_ciphertext, + fd_zksdk_transcript_t * transcript ) { + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L174-L179 */ + if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) + || fd_memeq( grouped_ciphertext->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L181-187 */ + grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, pubkey3, grouped_ciphertext ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L188-194 */ + return fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( + proof, + pubkey1, + pubkey2, + pubkey3, + grouped_ciphertext->commitment, + grouped_ciphertext->handles[0].handle, + grouped_ciphertext->handles[1].handle, + grouped_ciphertext->handles[2].handle, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + transcript + ); +} + +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L198 */ +int +fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( + fd_zksdk_grp_ciph_3h_val_proof_t const * proof, + uchar const pubkey1 [ 32 ], + uchar const pubkey2 [ 32 ], + uchar const pubkey3 [ 32 ], + uchar const comm [ 32 ], + uchar const handle1 [ 32 ], + uchar const handle2 [ 32 ], + uchar const handle3 [ 32 ], + uchar const comm_hi [ 32 ], + uchar const handle1_hi [ 32 ], + uchar const handle2_hi [ 32 ], + uchar const handle3_hi [ 32 ], + uchar const challenge_t[ 32 ], + int const batched, + fd_zksdk_transcript_t * transcript ) { + /* + When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi, h3_hi are NULL. + When batched==true, they are computed as C = C_lo + t C_hi. + + We store points and scalars in the following arrays: + + points scalars + 0 G z_x + 1 H z_r + 2 C -c + 3 pub1 w z_r + 4 Y_1 -w + 5 h1 -w c + 6 pub2 ww z_r + 7 Y_2 -ww + 8 h2 -ww c + 9 pub3 www z_r + 10 Y_3 -www + 11 h3 -www c + 12 C_hi -c t (if batched) + 13 h1_hi -c w t (if batched) + 14 h2_hi -c ww t (if batched) + 15 h3_hi -c www t (if batched) + ----------------------- MSM + Y_0 + */ + + /* Validate all inputs */ + uchar scalars[ 16 * 32 ]; + fd_ristretto255_point_t points[16]; + fd_ristretto255_point_t y0[1]; + fd_ristretto255_point_t res[1]; + + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G ); + fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H ); + if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], comm )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], pubkey1 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->y1 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], handle1 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], pubkey2 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], proof->y2 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[8], handle2 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[9], pubkey3 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[10], proof->y3 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[11], handle3 )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + if (batched) { + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[12], comm_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[13], handle1_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[14], handle2_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[15], handle3_hi )==NULL ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + } + + /* Finalize transcript and extract challenges */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L206 */ + fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 3 ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L208-L220 */ + int val = FD_TRANSCRIPT_SUCCESS; + val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); + val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); + val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2); + if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + /* Y_3 can be zero */ + fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_3"), proof->y3); + + uchar c[ 32 ]; + uchar w[ 32 ]; + fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); + + fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_x"), proof->zx ); + fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_r"), proof->zr ); + + fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L221-L290 + Note: we use a slightly different MSM but they're equivalent. */ + + /* Compute scalars */ + fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx ); // z_x + fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr ); // z_r + fd_curve25519_scalar_neg( &scalars[ 2*32 ], c ); // -c + fd_curve25519_scalar_mul( &scalars[ 3*32 ], proof->zr, w ); // w z_r + fd_curve25519_scalar_neg( &scalars[ 4*32 ], w ); // -w + fd_curve25519_scalar_mul( &scalars[ 5*32 ], &scalars[ 2*32 ], w ); // -w c + fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 3*32 ], w ); // ww z_r + fd_curve25519_scalar_mul( &scalars[ 7*32 ], &scalars[ 4*32 ], w ); // -ww + fd_curve25519_scalar_mul( &scalars[ 8*32 ], &scalars[ 5*32 ], w ); // -ww c + fd_curve25519_scalar_mul( &scalars[ 9*32 ], &scalars[ 6*32 ], w ); // www z_r + fd_curve25519_scalar_mul( &scalars[ 10*32 ], &scalars[ 7*32 ], w ); // -www + fd_curve25519_scalar_mul( &scalars[ 11*32 ], &scalars[ 8*32 ], w ); // -www c + if( batched ) { + fd_curve25519_scalar_mul( &scalars[ 12*32 ], &scalars[ 2*32 ], challenge_t ); // -c t + fd_curve25519_scalar_mul( &scalars[ 13*32 ], &scalars[ 5*32 ], challenge_t ); // -c w t + fd_curve25519_scalar_mul( &scalars[ 14*32 ], &scalars[ 8*32 ], challenge_t ); // -c ww t + fd_curve25519_scalar_mul( &scalars[ 15*32 ], &scalars[ 11*32 ], challenge_t ); // -c www t + } + + /* Compute the final MSM */ + fd_ristretto255_multi_scalar_mul( res, scalars, points, batched ? 16 : 12 ); + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L292-L296 */ + if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { + return FD_ZKSDK_VERIFY_PROOF_SUCCESS; + } + return FD_ZKSDK_VERIFY_PROOF_ERROR; +} + +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_3.rs#L118 */ int fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; @@ -17,20 +229,12 @@ fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity( void const * fd_zksdk_grp_ciph_3h_val_context_t const * context = _context; fd_zksdk_grp_ciph_3h_val_proof_t const * proof = _proof; - return fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( + return fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity( proof, context->pubkey1, context->pubkey2, context->pubkey3, - context->grouped_ciphertext.commitment, - context->grouped_ciphertext.handles[0].handle, - context->grouped_ciphertext.handles[1].handle, - context->grouped_ciphertext.handles[2].handle, - NULL, - NULL, - NULL, - NULL, - 0, + context->grouped_ciphertext, transcript ); } diff --git a/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c b/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c index cf340df1fff..b7d0d6c365f 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c @@ -117,7 +117,7 @@ fd_zksdk_verify_proof_percentage_with_cap( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L482-L513 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L482-L513 Note: we use a slightly different MSM but they're equivalent. */ uchar ww[ 32 ]; fd_curve25519_scalar_mul( ww, w, w ); From 658e30e8c0a977b2a4c91b7436e4222b670f902a Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Wed, 11 Feb 2026 23:35:48 +0000 Subject: [PATCH 4/7] zksdk: upgrade range proofs instructions --- .../fd_zksdk_batched_range_proof_u128.c | 51 +++++++++-------- .../fd_zksdk_batched_range_proof_u256.c | 54 +++++++++--------- .../fd_zksdk_batched_range_proof_u64.c | 51 +++++++++-------- .../fd_zksdk_batched_range_proofs.h | 55 ++++++++++++------- src/ballet/zksdk/rangeproofs/fd_rangeproofs.c | 5 +- 5 files changed, 116 insertions(+), 100 deletions(-) diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c index c73f2519439..80f000734bc 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c @@ -1,13 +1,29 @@ #include "../fd_zksdk_private.h" -static inline int -fd_zksdk_verify_proof_range_u128( - fd_zksdk_range_proof_u128_proof_t const * proof, - uchar const commitments [ 32 ], - uchar const bit_lengths [ 1 ], - uchar const batch_len, - fd_zksdk_transcript_t * transcript ) { +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L83 */ +int +fd_zksdk_instr_verify_proof_batched_range_proof_u128( void const * _context, void const * _proof ) { + fd_zksdk_transcript_t transcript[1]; + fd_zksdk_batched_range_proof_context_t const * context = _context; + fd_zksdk_range_proof_u128_proof_t const * proof = _proof; + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L84 */ + uchar batch_len = 0; + int val = batched_range_proof_context_try_into( &batch_len, context ); + if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { + return val; + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L87-L89 + This can never happen: `commitments: [PodPedersenCommitment; MAX_COMMITMENTS]` */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L91-L99 + We validate this inside fd_rangeproofs_verify() */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L101 */ + batched_range_proof_context_new_transcript( transcript, context ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L104-L106 */ const fd_rangeproofs_ipp_proof_t ipp_proof = { 7, proof->ipp_lr_vec, @@ -17,8 +33,8 @@ fd_zksdk_verify_proof_range_u128( int res = fd_rangeproofs_verify( &proof->range_proof, &ipp_proof, - commitments, - bit_lengths, + context->commitments, + context->bit_lengths, batch_len, transcript ); @@ -28,20 +44,3 @@ fd_zksdk_verify_proof_range_u128( } return FD_ZKSDK_VERIFY_PROOF_ERROR; } - -int -fd_zksdk_instr_verify_proof_batched_range_proof_u128( void const * _context, void const * _proof ) { - fd_zksdk_transcript_t transcript[1]; - fd_zksdk_batched_range_proof_context_t const * context = _context; - fd_zksdk_range_proof_u128_proof_t const * proof = _proof; - - uchar batch_len = 0; - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82-L91 */ - int val = batched_range_proof_init_and_validate( &batch_len, context, transcript ); - if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { - return val; - } - - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L93-L95 */ - return fd_zksdk_verify_proof_range_u128( proof, context->commitments, context->bit_lengths, batch_len, transcript ); -} diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c index e8554853f1a..60f5dfb42f7 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c @@ -1,13 +1,32 @@ #include "../fd_zksdk_private.h" -static inline int -fd_zksdk_verify_proof_range_u256( - fd_zksdk_range_proof_u256_proof_t const * proof, - uchar const commitments [ 32 ], - uchar const bit_lengths [ 1 ], - uchar const batch_len, - fd_zksdk_transcript_t * transcript ) { +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L90 */ +int +fd_zksdk_instr_verify_proof_batched_range_proof_u256( void const * _context, void const * _proof ) { + fd_zksdk_transcript_t transcript[1]; + fd_zksdk_batched_range_proof_context_t const * context = _context; + fd_zksdk_range_proof_u256_proof_t const * proof = _proof; + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L91 */ + uchar batch_len = 0; + int val = batched_range_proof_context_try_into( &batch_len, context ); + if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { + return val; + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L99-L104 + This is already checked in batched_range_proof_context_try_into() */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L106-L108 + This can never happen: `commitments: [PodPedersenCommitment; MAX_COMMITMENTS]` */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L110-L117 + We validate this inside fd_rangeproofs_verify() */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L119 */ + batched_range_proof_context_new_transcript( transcript, context ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L122-L124 */ const fd_rangeproofs_ipp_proof_t ipp_proof = { 8, proof->ipp_lr_vec, @@ -17,8 +36,8 @@ fd_zksdk_verify_proof_range_u256( int res = fd_rangeproofs_verify( &proof->range_proof, &ipp_proof, - commitments, - bit_lengths, + context->commitments, + context->bit_lengths, batch_len, transcript ); @@ -28,20 +47,3 @@ fd_zksdk_verify_proof_range_u256( } return FD_ZKSDK_VERIFY_PROOF_ERROR; } - -int -fd_zksdk_instr_verify_proof_batched_range_proof_u256( void const * _context, void const * _proof ) { - fd_zksdk_transcript_t transcript[1]; - fd_zksdk_batched_range_proof_context_t const * context = _context; - fd_zksdk_range_proof_u256_proof_t const * proof = _proof; - - uchar batch_len = 0; - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82-L91 */ - int val = batched_range_proof_init_and_validate( &batch_len, context, transcript ); - if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { - return val; - } - - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L93-L95 */ - return fd_zksdk_verify_proof_range_u256( proof, context->commitments, context->bit_lengths, batch_len, transcript ); -} diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c index 6bd4037178a..469e7a99bcc 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c @@ -1,13 +1,29 @@ #include "../fd_zksdk_private.h" -static inline int -fd_zksdk_verify_proof_range_u64( - fd_zksdk_range_proof_u64_proof_t const * proof, - uchar const commitments [ 32 ], - uchar const bit_lengths [ 1 ], - uchar const batch_len, - fd_zksdk_transcript_t * transcript ) { +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82 */ +int +fd_zksdk_instr_verify_proof_batched_range_proof_u64( void const * _context, void const * _proof ) { + fd_zksdk_transcript_t transcript[1]; + fd_zksdk_batched_range_proof_context_t const * context = _context; + fd_zksdk_range_proof_u64_proof_t const * proof = _proof; + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L83 */ + uchar batch_len = 0; + int val = batched_range_proof_context_try_into( &batch_len, context ); + if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { + return val; + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L86-L88 + This can never happen: `commitments: [PodPedersenCommitment; MAX_COMMITMENTS]` */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L90-L98 + We validate this inside fd_rangeproofs_verify() */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L100 */ + batched_range_proof_context_new_transcript( transcript, context ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L103-L105 */ const fd_rangeproofs_ipp_proof_t ipp_proof = { 6, proof->ipp_lr_vec, @@ -17,8 +33,8 @@ fd_zksdk_verify_proof_range_u64( int res = fd_rangeproofs_verify( &proof->range_proof, &ipp_proof, - commitments, - bit_lengths, + context->commitments, + context->bit_lengths, batch_len, transcript ); @@ -28,20 +44,3 @@ fd_zksdk_verify_proof_range_u64( } return FD_ZKSDK_VERIFY_PROOF_ERROR; } - -int -fd_zksdk_instr_verify_proof_batched_range_proof_u64( void const * _context, void const * _proof ) { - fd_zksdk_transcript_t transcript[1]; - fd_zksdk_batched_range_proof_context_t const * context = _context; - fd_zksdk_range_proof_u64_proof_t const * proof = _proof; - - uchar batch_len = 0; - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82-L91 */ - int val = batched_range_proof_init_and_validate( &batch_len, context, transcript ); - if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { - return val; - } - - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L93-L95 */ - return fd_zksdk_verify_proof_range_u64( proof, context->commitments, context->bit_lengths, batch_len, transcript ); -} diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h index c5d3e388ac0..211fa1b2b74 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h @@ -34,39 +34,54 @@ struct __attribute__((packed)) fd_zksdk_batched_range_proof_context { }; typedef struct fd_zksdk_batched_range_proof_context fd_zksdk_batched_range_proof_context_t; +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L63 */ static inline void -batched_range_proof_transcript_init( fd_zksdk_transcript_t * transcript, - fd_zksdk_batched_range_proof_context_t const * context) { +batched_range_proof_context_new_transcript( fd_zksdk_transcript_t * transcript, + fd_zksdk_batched_range_proof_context_t const * context) { fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-range-proof-instruction") ); fd_merlin_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("commitments"), context->commitments, FD_ZKSDK_MAX_COMMITMENTS * 32 ); fd_merlin_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("bit-lengths"), context->bit_lengths, FD_ZKSDK_MAX_COMMITMENTS ); } -/* batched_range_proof_init_and_validate implements verify_proof() for range proofs: - https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82 - It validates context, initializes the transcript, and returns the length of - commitments / bit_lengths, i.e. the size of the batch in the batch proof, aka m. - For compatibility with Agave, this is the critical rule: - https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L112 - i.e., the length is determined by the first all-zero commitment. - Note that Agave is decompressing points while parsing the context, we don't do - that here but at the very beginning of the ZKP verify, e.g. fd_zksdk_verify_proof_range_u128(). */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L117 */ static inline int -batched_range_proof_init_and_validate( uchar * len, - fd_zksdk_batched_range_proof_context_t const * context, - fd_zksdk_transcript_t * transcript ) { +batched_range_proof_context_try_into( uchar * _len, + fd_zksdk_batched_range_proof_context_t const * context ) { - uchar i = 0; - for( ; i < FD_ZKSDK_MAX_COMMITMENTS; i++ ) { - if( fd_memeq( &context->commitments[ i*32 ], fd_ristretto255_compressed_zero, 32 ) ) { + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L118-L121 + Compute len as index of first commitment set to zero. */ + uchar len = 0; + for( ; lencommitments[ len*32 ], fd_ristretto255_compressed_zero, 32 ) ) { break; } } - *len = i; - //TODO: https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L87 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L134-L136 */ + if( FD_UNLIKELY( len == 0 ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L139-L144 + All bit lengths must be non-zero and <= 64. */ + for( uchar i=0; ibit_lengths[ i ]==0 || context->bit_lengths[ i ]>64 ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + } + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L147-L158 + All commitments and bit lengths after len must be zero. */ + for( uchar i=len; icommitments[ i*32 ], fd_ristretto255_compressed_zero, 32 ) + || context->bit_lengths[ i ]!=0 + ) ) { + return FD_ZKSDK_VERIFY_PROOF_ERROR; + } + } - batched_range_proof_transcript_init( transcript, context ); + *_len = len; return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } diff --git a/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c b/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c index 33a73fbd4a2..e45c4bc84b0 100644 --- a/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c +++ b/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c @@ -44,6 +44,7 @@ fd_rangeproofs_delta( } } +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/range_proof/mod.rs#L324 */ int fd_rangeproofs_verify( fd_rangeproofs_range_proof_t const * range_proof, @@ -350,12 +351,12 @@ fd_rangeproofs_verify( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, idx ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/range_proof/mod.rs#L441-L445 */ if( FD_LIKELY( fd_ristretto255_point_eq_neg( res, a_res ) ) ) { return FD_RANGEPROOFS_SUCCESS; } - + return FD_RANGEPROOFS_ERROR; #undef LOGN #undef N #undef MAX - return FD_RANGEPROOFS_ERROR; } From 67b7006a6233064e361f66188fcbc914d5ad036c Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Fri, 13 Feb 2026 16:51:27 +0000 Subject: [PATCH 5/7] zksdk: upgrade to 5.0.1 --- src/ballet/zksdk/fd_zksdk.h | 4 +-- ...ed_grouped_ciphertext_2_handles_validity.c | 14 ++++---- ...ed_grouped_ciphertext_3_handles_validity.c | 14 ++++---- .../fd_zksdk_batched_range_proof_u128.c | 12 +++---- .../fd_zksdk_batched_range_proof_u256.c | 14 ++++---- .../fd_zksdk_batched_range_proof_u64.c | 12 +++---- .../fd_zksdk_batched_range_proofs.h | 12 +++---- .../fd_zksdk_ciphertext_ciphertext_equality.c | 16 +++++----- .../fd_zksdk_ciphertext_commitment_equality.c | 14 ++++---- ...dk_grouped_ciphertext_2_handles_validity.c | 20 ++++++------ ...dk_grouped_ciphertext_3_handles_validity.c | 22 ++++++------- .../fd_zksdk_percentage_with_cap.c | 16 +++++----- .../instructions/fd_zksdk_pubkey_validity.c | 16 +++++----- .../instructions/fd_zksdk_zero_ciphertext.c | 16 +++++----- src/ballet/zksdk/rangeproofs/fd_rangeproofs.c | 4 +-- .../rangeproofs/fd_rangeproofs_transcript.h | 2 +- .../zksdk/transcript/fd_zksdk_transcript.h | 2 +- .../program/fd_zk_elgamal_proof_program.c | 32 +++++++++++-------- 18 files changed, 124 insertions(+), 118 deletions(-) diff --git a/src/ballet/zksdk/fd_zksdk.h b/src/ballet/zksdk/fd_zksdk.h index c5f0dd47196..db67abf6173 100644 --- a/src/ballet/zksdk/fd_zksdk.h +++ b/src/ballet/zksdk/fd_zksdk.h @@ -4,7 +4,7 @@ #include "fd_zksdk_common.h" /* FD_ZKSDK_INSTR_{...} identify ZK ElGamal Proof Program instructions. - https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/instruction.rs#L53 */ + https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/instruction.rs#L53 */ #define FD_ZKSDK_INSTR_CLOSE_CONTEXT_STATE ((uchar) 0) #define FD_ZKSDK_INSTR_VERIFY_ZERO_CIPHERTEXT ((uchar) 1) @@ -65,7 +65,7 @@ static const ulong fd_zksdk_proof_sz[] = { }; /* ProofContextStateMeta - https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/state.rs#L71 */ + https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/state.rs#L71 */ struct __attribute__((packed)) fd_zksdk_proof_ctx_state_meta { uchar ctx_state_authority[ 32 ]; uchar proof_type; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c index 1e892fa08e7..c2f4e486115 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L163 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L163 */ static inline void batched_grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transcript, uchar const pubkey1 [ 32 ], @@ -14,7 +14,7 @@ batched_grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transc fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)grouped_ciphertext_hi, sizeof(grp_ciph_2h_t) ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L106 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L106 */ static inline int fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2h_val_proof_t const * proof, @@ -24,22 +24,22 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( grp_ciph_2h_t const * grouped_ciphertext_hi, fd_zksdk_transcript_t * transcript ) { - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L117-L122 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L117-L122 */ if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( grouped_ciphertext_lo->commitment, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( grouped_ciphertext_hi->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L124-L131 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L124-L131 */ batched_grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, grouped_ciphertext_lo, grouped_ciphertext_hi ); fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 2 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L133 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L133 */ uchar t[ 32 ]; fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L135-L160 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_2.rs#L135-L160 Note: in our impl, t is embedded in the final MSM. */ return fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( proof, @@ -57,7 +57,7 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity( ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_2.rs#L126 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_2.rs#L126 */ int fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_2_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c index 47ef164e5a3..e121a9cb470 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_grouped_ciphertext_3_handles_validity.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L180 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L180 */ static inline void batched_grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transcript, @@ -16,7 +16,7 @@ batched_grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)grouped_ciphertext_hi, sizeof(grp_ciph_3h_t) ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L111 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L111 */ static inline int fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( fd_zksdk_grp_ciph_3h_val_proof_t const * proof, @@ -27,7 +27,7 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( grp_ciph_3h_t const * grouped_ciphertext_hi, fd_zksdk_transcript_t * transcript ) { - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L123-L129 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L123-L129 */ if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( grouped_ciphertext_lo->commitment, fd_ristretto255_compressed_zero, 32 ) @@ -35,15 +35,15 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( return FD_ZKSDK_VERIFY_PROOF_ERROR; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L131-L139 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L131-L139 */ batched_grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, pubkey3, grouped_ciphertext_lo, grouped_ciphertext_hi ); fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 3 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L141 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L141 */ uchar t[ 32 ]; fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L143-L177 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/batched_grouped_ciphertext_validity/handles_3.rs#L143-L177 Note: in our impl, t is embedded in the final MSM. */ return fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( proof, @@ -64,7 +64,7 @@ fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity( ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_3.rs#L138 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_grouped_ciphertext_validity/handles_3.rs#L138 */ int fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c index 80f000734bc..3b3e369097e 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u128.c @@ -1,29 +1,29 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L83 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L83 */ int fd_zksdk_instr_verify_proof_batched_range_proof_u128( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; fd_zksdk_batched_range_proof_context_t const * context = _context; fd_zksdk_range_proof_u128_proof_t const * proof = _proof; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L84 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L84 */ uchar batch_len = 0; int val = batched_range_proof_context_try_into( &batch_len, context ); if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { return val; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L87-L89 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L87-L89 This can never happen: `commitments: [PodPedersenCommitment; MAX_COMMITMENTS]` */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L91-L99 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L91-L99 We validate this inside fd_rangeproofs_verify() */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L101 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L101 */ batched_range_proof_context_new_transcript( transcript, context ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L104-L106 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u128.rs#L104-L106 */ const fd_rangeproofs_ipp_proof_t ipp_proof = { 7, proof->ipp_lr_vec, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c index 60f5dfb42f7..7737a22e0e7 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u256.c @@ -1,32 +1,32 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L90 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L90 */ int fd_zksdk_instr_verify_proof_batched_range_proof_u256( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; fd_zksdk_batched_range_proof_context_t const * context = _context; fd_zksdk_range_proof_u256_proof_t const * proof = _proof; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L91 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L91 */ uchar batch_len = 0; int val = batched_range_proof_context_try_into( &batch_len, context ); if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { return val; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L99-L104 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L99-L104 This is already checked in batched_range_proof_context_try_into() */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L106-L108 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L106-L108 This can never happen: `commitments: [PodPedersenCommitment; MAX_COMMITMENTS]` */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L110-L117 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L110-L117 We validate this inside fd_rangeproofs_verify() */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L119 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L119 */ batched_range_proof_context_new_transcript( transcript, context ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L122-L124 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u256.rs#L122-L124 */ const fd_rangeproofs_ipp_proof_t ipp_proof = { 8, proof->ipp_lr_vec, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c index 469e7a99bcc..2399a814882 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proof_u64.c @@ -1,29 +1,29 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L82 */ int fd_zksdk_instr_verify_proof_batched_range_proof_u64( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; fd_zksdk_batched_range_proof_context_t const * context = _context; fd_zksdk_range_proof_u64_proof_t const * proof = _proof; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L83 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L83 */ uchar batch_len = 0; int val = batched_range_proof_context_try_into( &batch_len, context ); if( FD_UNLIKELY( val != FD_ZKSDK_VERIFY_PROOF_SUCCESS ) ) { return val; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L86-L88 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L86-L88 This can never happen: `commitments: [PodPedersenCommitment; MAX_COMMITMENTS]` */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L90-L98 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L90-L98 We validate this inside fd_rangeproofs_verify() */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L100 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L100 */ batched_range_proof_context_new_transcript( transcript, context ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L103-L105 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/batched_range_proof_u64.rs#L103-L105 */ const fd_rangeproofs_ipp_proof_t ipp_proof = { 6, proof->ipp_lr_vec, diff --git a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h index 211fa1b2b74..a08ba179228 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h +++ b/src/ballet/zksdk/instructions/fd_zksdk_batched_range_proofs.h @@ -34,7 +34,7 @@ struct __attribute__((packed)) fd_zksdk_batched_range_proof_context { }; typedef struct fd_zksdk_batched_range_proof_context fd_zksdk_batched_range_proof_context_t; -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L63 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L63 */ static inline void batched_range_proof_context_new_transcript( fd_zksdk_transcript_t * transcript, fd_zksdk_batched_range_proof_context_t const * context) { @@ -43,12 +43,12 @@ batched_range_proof_context_new_transcript( fd_zksdk_transcript_t * fd_merlin_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("bit-lengths"), context->bit_lengths, FD_ZKSDK_MAX_COMMITMENTS ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L117 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L117 */ static inline int batched_range_proof_context_try_into( uchar * _len, fd_zksdk_batched_range_proof_context_t const * context ) { - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L118-L121 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L118-L121 Compute len as index of first commitment set to zero. */ uchar len = 0; for( ; lenbit_lengths[ i ]==0 || context->bit_lengths[ i ]>64 ) ) { @@ -70,7 +70,7 @@ batched_range_proof_context_try_into( uchar * } } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L147-L158 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/batched_range_proof/mod.rs#L147-L158 All commitments and bit lengths after len must be zero. */ for( uchar i=len; iy0); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); @@ -124,7 +124,7 @@ fd_zksdk_verify_proof_ciphertext_ciphertext_equality( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L196-L254 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L196-L254 Note: we use a slightly different MSM but they're equivalent. */ uchar ww[ 32 ]; fd_curve25519_scalar_mul( ww, w, w ); @@ -148,14 +148,14 @@ fd_zksdk_verify_proof_ciphertext_ciphertext_equality( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 11 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L256-L260 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L256-L260 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/ciphertext_ciphertext_equality.rs#L122 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/ciphertext_ciphertext_equality.rs#L122 */ int fd_zksdk_instr_verify_proof_ciphertext_ciphertext_equality( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c b/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c index c646cfcd544..dbb70deec2b 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_ciphertext_commitment_equality.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L229 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L229 */ static inline void ciph_comm_eq_hash_context( fd_zksdk_transcript_t * transcript, uchar const pubkey [ 32 ], @@ -11,7 +11,7 @@ ciph_comm_eq_hash_context( fd_zksdk_transcript_t * transcript, fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("commitment"), commitment ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L139 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L139 */ int fd_zksdk_verify_proof_ciphertext_commitment_equality( fd_zksdk_ciph_comm_eq_proof_t const * proof, @@ -49,7 +49,7 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( fd_ristretto255_point_t y2[1]; fd_ristretto255_point_t res[1]; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L146-L152 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L146-L152 */ if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( &ciphertext[0], fd_ristretto255_compressed_zero, 32 ) || fd_memeq( &ciphertext[32], fd_ristretto255_compressed_zero, 32 ) @@ -93,11 +93,11 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( /* Finalize transcript and extract challenges */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L154-L155 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L154-L155 */ ciph_comm_eq_hash_context( transcript, pubkey, ciphertext, commitment ); fd_zksdk_transcript_domsep_ciph_comm_eq_proof( transcript ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L158-L173 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L158-L173 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); @@ -116,7 +116,7 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L174-L220 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L174-L220 Note: we use a slightly different MSM but they're equivalent. */ /* Compute scalars */ @@ -132,7 +132,7 @@ fd_zksdk_verify_proof_ciphertext_commitment_equality( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 8 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L222-L226 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/ciphertext_commitment_equality.rs#L222-L226 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y2 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } diff --git a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c index 79e704b6794..c8a75f7c50f 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_2_handles_validity.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161 */ static inline void grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transcript, uchar const pubkey1 [ 32 ], @@ -17,16 +17,16 @@ fd_zksdk_verify_proof_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2 uchar const pubkey2 [ 32 ], grp_ciph_2h_t const * grouped_ciphertext, fd_zksdk_transcript_t * transcript ) { - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L155-L159 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L155-L159 */ if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( grouped_ciphertext->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161-L166 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L161-L166 */ grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, grouped_ciphertext ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L167 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L167 */ return fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( proof, pubkey1, @@ -43,7 +43,7 @@ fd_zksdk_verify_proof_grouped_ciphertext_2_handles_validity( fd_zksdk_grp_ciph_2 ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L170 +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L170 In Agave, the verify_direct() is a method of the NON-batched proof. The batched proof is converted into a non-batched proof with 3 mul. However, verify_direct() is doing a MSM so we can embed the 3 mul @@ -163,10 +163,10 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( /* Finalize transcript and extract challenges */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L177 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L177 */ fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 2 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L179-L189 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L179-L189 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); @@ -185,7 +185,7 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L190-L244 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L190-L244 Note: we use a slightly different MSM but they're equivalent. */ /* Compute scalars */ @@ -212,14 +212,14 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_2_handles_validity( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, idx ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L246-L250 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_2.rs#L246-L250 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_2.rs#L109 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_2.rs#L109 */ int fd_zksdk_instr_verify_proof_grouped_ciphertext_2_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c index 70c9d96033c..0154146d921 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_grouped_ciphertext_3_handles_validity.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L299 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L299 */ static inline void grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_t * transcript, @@ -14,7 +14,7 @@ grouped_ciphertext_validity_hash_context( fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)grouped_ciphertext, sizeof(grp_ciph_3h_t) ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L163 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L163 */ static inline int fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity( fd_zksdk_grp_ciph_3h_val_proof_t const * proof, @@ -24,17 +24,17 @@ fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity( grp_ciph_3h_t const * grouped_ciphertext, fd_zksdk_transcript_t * transcript ) { - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L174-L179 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L174-L179 */ if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( grouped_ciphertext->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L181-187 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L181-187 */ grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, pubkey3, grouped_ciphertext ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L188-194 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L188-194 */ return fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( proof, pubkey1, @@ -54,7 +54,7 @@ fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity( ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L198 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L198 */ int fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( fd_zksdk_grp_ciph_3h_val_proof_t const * proof, @@ -165,10 +165,10 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( /* Finalize transcript and extract challenges */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L206 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L206 */ fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 3 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L208-L220 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L208-L220 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0); val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1); @@ -188,7 +188,7 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L221-L290 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L221-L290 Note: we use a slightly different MSM but they're equivalent. */ /* Compute scalars */ @@ -214,14 +214,14 @@ fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, batched ? 16 : 12 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L292-L296 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L292-L296 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_3.rs#L118 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_3.rs#L118 */ int fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c b/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c index b7d0d6c365f..5aa8420dc48 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_percentage_with_cap.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L522 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L522 */ static inline void percentage_with_cap_hash_context( fd_zksdk_transcript_t * transcript, uchar const percentage_commitment[ 32 ], @@ -13,7 +13,7 @@ percentage_with_cap_hash_context( fd_zksdk_transcript_t * transcript, fd_merlin_transcript_append_u64 ( transcript, FD_TRANSCRIPT_LITERAL("max-value"), max_value ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L413 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L413 */ static inline int fd_zksdk_verify_proof_percentage_with_cap( fd_zksdk_percentage_with_cap_proof_t const * proof, @@ -43,7 +43,7 @@ fd_zksdk_verify_proof_percentage_with_cap( fd_ristretto255_point_t y[1]; fd_ristretto255_point_t res[1]; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L421-L426 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L421-L426 */ if( FD_UNLIKELY( fd_memeq( percentage_commitment, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( delta_commitment, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( claimed_commitment, fd_ristretto255_compressed_zero, 32 ) ) ) { @@ -89,11 +89,11 @@ fd_zksdk_verify_proof_percentage_with_cap( /* Finalize transcript and extract challenges */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L428-L435 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L428-L435 */ percentage_with_cap_hash_context( transcript, percentage_commitment, delta_commitment, claimed_commitment, max_value ); fd_zksdk_transcript_domsep_percentage_with_cap_proof( transcript ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L438-L481 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L438-L481 */ uchar m[ 32 ]; fd_curve25519_scalar_from_u64( m, max_value ); @@ -117,7 +117,7 @@ fd_zksdk_verify_proof_percentage_with_cap( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L482-L513 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L482-L513 Note: we use a slightly different MSM but they're equivalent. */ uchar ww[ 32 ]; fd_curve25519_scalar_mul( ww, w, w ); @@ -149,14 +149,14 @@ fd_zksdk_verify_proof_percentage_with_cap( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 7 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L515-L519 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/percentage_with_cap.rs#L515-L519 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/percentage_with_cap.rs#L133 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/percentage_with_cap.rs#L133 */ int fd_zksdk_instr_verify_proof_percentage_with_cap( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c b/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c index 9abc1f9ab9e..d21a86a36f8 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_pubkey_validity.c @@ -1,13 +1,13 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L128 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L128 */ static inline void pubkey_validity_hash_context( fd_zksdk_transcript_t * transcript, uchar const pubkey[ 32 ] ) { fd_zksdk_transcript_append_pubkey( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), pubkey ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L91 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L91 */ static inline int fd_zksdk_verify_proof_pubkey_validity( fd_zksdk_pubkey_validity_proof_t const * proof, @@ -26,11 +26,11 @@ fd_zksdk_verify_proof_pubkey_validity( fd_ristretto255_point_t y[1]; fd_ristretto255_point_t res[1]; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L96-L97 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L96-L97 */ pubkey_validity_hash_context( transcript, pubkey ); fd_zksdk_transcript_domsep_pubkey_proof( transcript ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L102-L104 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L102-L104 */ if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) ) ) { return FD_ZKSDK_VERIFY_PROOF_ERROR; } @@ -50,7 +50,7 @@ fd_zksdk_verify_proof_pubkey_validity( } /* Finalize transcript and extract challenges - https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L107-L108 */ + https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L107-L108 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y"), proof->y); if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { @@ -60,7 +60,7 @@ fd_zksdk_verify_proof_pubkey_validity( uchar c[ 32 ]; fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L111-L119 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L111-L119 Note: we use a slightly different MSM but they're equivalent. */ /* Compute scalars */ @@ -70,14 +70,14 @@ fd_zksdk_verify_proof_pubkey_validity( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 2 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L121-L125 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/pubkey_validity.rs#L121-L125 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/pubkey_validity.rs#L73 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/pubkey_validity.rs#L73 */ int fd_zksdk_instr_verify_proof_pubkey_validity( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c b/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c index 79df6131129..c084b121baa 100644 --- a/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c +++ b/src/ballet/zksdk/instructions/fd_zksdk_zero_ciphertext.c @@ -1,6 +1,6 @@ #include "../fd_zksdk_private.h" -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L166 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L167 */ static inline void zero_ciphertext_hash_context( fd_zksdk_transcript_t * transcript, uchar const pubkey [ 32 ], @@ -9,7 +9,7 @@ zero_ciphertext_hash_context( fd_zksdk_transcript_t * transcript, fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), ciphertext ); } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L98 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L98 */ static inline int fd_zksdk_verify_proof_zero_ciphertext( fd_zksdk_zero_ciphertext_proof_t const * proof, @@ -42,7 +42,7 @@ fd_zksdk_verify_proof_zero_ciphertext( fd_ristretto255_point_t y[1]; fd_ristretto255_point_t res[1]; - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L104-L108 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L104-L109 Reject identity pubkey and ciphertext.commitment. */ if( FD_UNLIKELY( fd_memeq( pubkey, fd_ristretto255_compressed_zero, 32 ) || fd_memeq( &ciphertext[0], fd_ristretto255_compressed_zero, 32 ) @@ -75,11 +75,11 @@ fd_zksdk_verify_proof_zero_ciphertext( /* Finalize transcript and extract challenges */ - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L110-L111 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L111-L112 */ zero_ciphertext_hash_context( transcript, pubkey, ciphertext ); fd_zksdk_transcript_domsep_zero_ciphertext_proof( transcript ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L118-L125 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L119-L126 */ int val = FD_TRANSCRIPT_SUCCESS; val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_P"), proof->yp); if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { @@ -95,7 +95,7 @@ fd_zksdk_verify_proof_zero_ciphertext( fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L140 + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L141 Note: we use a slightly different MSM but they're equivalent. */ /* Compute scalars */ @@ -108,14 +108,14 @@ fd_zksdk_verify_proof_zero_ciphertext( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, 5 ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L159-L163 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L160-L164 */ if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { return FD_ZKSDK_VERIFY_PROOF_SUCCESS; } return FD_ZKSDK_VERIFY_PROOF_ERROR; } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/proof_data/zero_ciphertext.rs#L88 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/zero_ciphertext.rs#L88 */ int fd_zksdk_instr_verify_proof_zero_ciphertext( void const * _context, void const * _proof ) { fd_zksdk_transcript_t transcript[1]; diff --git a/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c b/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c index e45c4bc84b0..9b6e35131b9 100644 --- a/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c +++ b/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c @@ -44,7 +44,7 @@ fd_rangeproofs_delta( } } -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/range_proof/mod.rs#L324 */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L324 */ int fd_rangeproofs_verify( fd_rangeproofs_range_proof_t const * range_proof, @@ -351,7 +351,7 @@ fd_rangeproofs_verify( /* Compute the final MSM */ fd_ristretto255_multi_scalar_mul( res, scalars, points, idx ); - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/range_proof/mod.rs#L441-L445 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L441-L445 */ if( FD_LIKELY( fd_ristretto255_point_eq_neg( res, a_res ) ) ) { return FD_RANGEPROOFS_SUCCESS; } diff --git a/src/ballet/zksdk/rangeproofs/fd_rangeproofs_transcript.h b/src/ballet/zksdk/rangeproofs/fd_rangeproofs_transcript.h index 5e492cb585d..1e0f1312ec4 100644 --- a/src/ballet/zksdk/rangeproofs/fd_rangeproofs_transcript.h +++ b/src/ballet/zksdk/rangeproofs/fd_rangeproofs_transcript.h @@ -1,7 +1,7 @@ #ifndef HEADER_fd_src_flamenco_runtime_program_rangeproofs_fd_transcript_h #define HEADER_fd_src_flamenco_runtime_program_rangeproofs_fd_transcript_h -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/transcript.rs */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/transcript.rs */ #include "../../merlin/fd_merlin.h" #include "../../ed25519/fd_ristretto255.h" diff --git a/src/ballet/zksdk/transcript/fd_zksdk_transcript.h b/src/ballet/zksdk/transcript/fd_zksdk_transcript.h index e17f2653c39..8a90c5e46c9 100644 --- a/src/ballet/zksdk/transcript/fd_zksdk_transcript.h +++ b/src/ballet/zksdk/transcript/fd_zksdk_transcript.h @@ -1,7 +1,7 @@ #ifndef HEADER_fd_src_ballet_zksdk_transcript_fd_transcript_h #define HEADER_fd_src_ballet_zksdk_transcript_fd_transcript_h -/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/transcript.rs +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/transcript.rs The implementation of transcript.rs is split between this file and rangeproofs/fd_rangeproofs_transcript.h. */ diff --git a/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c b/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c index 21b95d44396..b8da367d8c6 100644 --- a/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c +++ b/src/flamenco/runtime/program/fd_zk_elgamal_proof_program.c @@ -93,11 +93,11 @@ fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) { /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L51 */ accessed_accounts = 1U; - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L52-L63 + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L53-L64 Note: it doesn't look like Agave code can throw any error. */ uint proof_data_offset = fd_uint_load_4( &instr_data[1] ); - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L64-L67 + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L65-L68 Note: explcit cast to ulong just to call out that there can't be overflow */ if( (ulong)proof_data_offset+proof_data_sz > fd_borrowed_account_get_data_len( &proof_data_acc ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; @@ -111,7 +111,7 @@ fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) { } else { /* Case 2. Proof data from ix data. */ - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L80-L84 + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L81-L85 Note: instr_id is guaranteed to be valid, to access values in the arrays. */ if( ctx->instr->data_sz != 1 + proof_data_sz ) { fd_log_collector_msg_literal( ctx, "invalid proof data" ); @@ -121,13 +121,19 @@ fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) { } /* Verify individual ZKP - https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L73-L76 - https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L85-L88 */ + https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L74-L77 + https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L86-L89 */ + + /* TODO: we probably need an extra check to validate the length of sigma proofs, + see: https://github.com/solana-program/zk-elgamal-proof/pull/244 + However this check seems to be redundant for the case of ix data, and + seems to be missing only for accounts. It's also unclear what the result should be, + need to have explicit tests. */ void const * proof = context + fd_zksdk_context_sz[instr_id]; err = (*fd_zksdk_instr_verify_proof)( context, proof ); if( FD_UNLIKELY( err ) ) { //TODO: full log, including err - fd_log_collector_msg_literal( ctx, "proof_verification failed" ); + fd_log_collector_msg_literal( ctx, "proof verification failed" ); return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA; } @@ -135,7 +141,7 @@ fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) { https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L95-L98 */ if( instr_acc_cnt >= accessed_accounts + 2U ) { /* Obtain the context_state_authority by borrowing the account temporarily in a local scope. - https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L95-L100 */ + https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L100-L102 */ fd_pubkey_t context_state_authority[1]; do { fd_guarded_borrowed_account_t _acc = {0}; @@ -144,18 +150,18 @@ fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) { } while(0); /* Borrow the proof context account - https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L102-L103 */ + https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L104-L105 */ fd_guarded_borrowed_account_t proof_context_acc = {0}; FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, accessed_accounts, &proof_context_acc ); - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L105-L107 */ + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L107-L109 */ if( FD_UNLIKELY( !fd_memeq( fd_borrowed_account_get_owner( &proof_context_acc ), &fd_solana_zk_elgamal_proof_program_id, sizeof(fd_pubkey_t) ) ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER; } /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L111-L112 */ if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &proof_context_acc ) < CTX_META_SZ ) ) { - /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.0/zk-sdk/src/zk_elgamal_proof_program/state.rs#L83 */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/state.rs#L83 */ return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; } @@ -164,18 +170,18 @@ fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) { return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED; } - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L116-L117 */ + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L118-L119 */ fd_memcpy( context_state_data, context_state_authority, sizeof(fd_pubkey_t) ); /* context_state_data[0..31] */ context_state_data[ 32 ] = instr_id; /* context_state_data[32] */ fd_memcpy( context_state_data+CTX_META_SZ, context, context_sz ); /* context_state_data[33..] */ - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L119-L121 */ + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L121-L123 */ ulong context_state_data_sx = CTX_META_SZ + context_sz; if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &proof_context_acc ) != context_state_data_sx ) ) { return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; } - /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L123 */ + /* https://github.com/firedancer-io/agave/blob/v4.0.0-prerelease/programs/zk-elgamal-proof/src/lib.rs#L125 */ err = fd_borrowed_account_set_data_from_slice( &proof_context_acc, context_state_data, context_state_data_sx ); if( FD_UNLIKELY( err ) ) { return err; From 111310ee42e332f2f4451329f49bcbc70190cc16 Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Thu, 19 Feb 2026 18:27:50 +0000 Subject: [PATCH 6/7] zksdk: upgrade range proofs verify --- src/ballet/zksdk/rangeproofs/fd_rangeproofs.c | 81 ++++++++++--------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c b/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c index 9b6e35131b9..831c6d6abb8 100644 --- a/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c +++ b/src/ballet/zksdk/rangeproofs/fd_rangeproofs.c @@ -1,16 +1,6 @@ #include "fd_rangeproofs.h" -static inline int -batched_range_proof_validate_bits( ulong bit_length ) { - if ( FD_LIKELY( - bit_length==1 || bit_length==2 || bit_length==4 || bit_length==8 || - bit_length==16 || bit_length==32 || bit_length==64 || bit_length==128 - ) ) { - return FD_RANGEPROOFS_SUCCESS; - } - return FD_RANGEPROOFS_ERROR; -} - +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L509 */ void fd_rangeproofs_delta( uchar delta[ 32 ], @@ -54,8 +44,7 @@ fd_rangeproofs_verify( uchar const batch_len, fd_merlin_transcript_t * transcript ) { - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/range_proof/mod.rs#L288 - + /* We need to verify a range proof, by computing a large MSM. We store points in the following array. @@ -134,13 +123,14 @@ fd_rangeproofs_verify( const ulong logn = ipp_proof->logn; const ulong n = 1UL << logn; - /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/range_proof/mod.rs#L294-L306 - total bit length (nm) should be a power of 2, and <= 256 == size of our generators table. */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L330-L338 + These checks are already done in batched_range_proof_context_try_into() */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L340-L344 + total bit length (nm) should be a power of 2, and equal to the sz of the range proof. + since n by definition is a power of 2, we can just check nm == n. */ ulong nm = 0; for( uchar i=0; ia); val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("S"), range_proof->s); + /* We need to invert a bunch of values, we collect them all in a single buffer to use batch inversion. */ uchar batchinv_in [ 32*(1+LOGN) ]; uchar batchinv_out[ 32*(1+LOGN) ]; uchar allinv[ 32 ]; - uchar *y = batchinv_in; + uchar *y_inv = batchinv_out; + uchar *y = batchinv_in; uchar z[ 32 ]; fd_rangeproofs_transcript_challenge_scalar( y, transcript, FD_TRANSCRIPT_LITERAL("y") ); fd_rangeproofs_transcript_challenge_scalar( z, transcript, FD_TRANSCRIPT_LITERAL("z") ); @@ -232,51 +227,59 @@ fd_rangeproofs_verify( fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("e_blinding"), range_proof->e_blinding); uchar w[ 32 ]; - uchar c[ 32 ]; + uchar _c[ 32 ]; + uchar d[ 32 ]; fd_rangeproofs_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); - /* c will be overwritten later: https://github.com/anza-xyz/agave/commit/fd63ecda7ae7d32fe4ee0f3c933af8f2d5759ea2 */ - fd_rangeproofs_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); + /* The challenge `c` is a legacy component from an older implementation. + It is now unused, but is kept here for backward compatibility. */ + fd_rangeproofs_transcript_challenge_scalar( _c, transcript, FD_TRANSCRIPT_LITERAL("c") ); /* Inner Product (sub)Proof */ - fd_rangeproofs_transcript_domsep_inner_product( transcript, nm ); - uchar *u = &batchinv_in [ 32 ]; // skip y uchar *u_inv = &batchinv_out[ 32 ]; // skip y_inv - for( ulong i=0; ivecs[ i ].l); - val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("R"), ipp_proof->vecs[ i ].r); - if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { - return FD_RANGEPROOFS_ERROR; + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L377 */ + { + /* https://github.com/solana-program/zk-elgamal-proof/blob/main/zk-sdk/src/range_proof/inner_product.rs#L246 */ + fd_rangeproofs_transcript_domsep_inner_product( transcript, nm ); + + for( ulong i=0; ivecs[ i ].l); + val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("R"), ipp_proof->vecs[ i ].r); + if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { + return FD_RANGEPROOFS_ERROR; + } + fd_rangeproofs_transcript_challenge_scalar( &u[ i*32 ], transcript, FD_TRANSCRIPT_LITERAL("u") ); } - fd_rangeproofs_transcript_challenge_scalar( &u[ i*32 ], transcript, FD_TRANSCRIPT_LITERAL("u") ); + fd_curve25519_scalar_batch_inv( batchinv_out, allinv, batchinv_in, logn+1 ); } - fd_curve25519_scalar_batch_inv( batchinv_out, allinv, batchinv_in, logn+1 ); fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("ipp_a"), ipp_proof->a ); fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("ipp_b"), ipp_proof->b ); - /* c is overwritten: https://github.com/anza-xyz/agave/commit/fd63ecda7ae7d32fe4ee0f3c933af8f2d5759ea2 */ - fd_rangeproofs_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("d") ); + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L387 */ + fd_rangeproofs_transcript_challenge_scalar( d, transcript, FD_TRANSCRIPT_LITERAL("d") ); /* Compute scalars */ + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L391-L411 */ + // H: - ( eb + c t_xb ) uchar const *eb = range_proof->e_blinding; uchar const *txb = range_proof->tx_blinding; - fd_curve25519_scalar_muladd( &scalars[ 1*32 ], c, txb, eb ); + fd_curve25519_scalar_muladd( &scalars[ 1*32 ], d, txb, eb ); fd_curve25519_scalar_neg( &scalars[ 1*32 ], &scalars[ 1*32 ] ); // S: x // T_1: c x // T_2: c x^2 fd_curve25519_scalar_set( &scalars[ 2*32 ], x ); - fd_curve25519_scalar_mul( &scalars[ 3*32 ], c, x ); + fd_curve25519_scalar_mul( &scalars[ 3*32 ], d, x ); fd_curve25519_scalar_mul( &scalars[ 4*32 ], &scalars[ 3*32 ], x ); // commitments: c z^2, c z^3 ... uchar zz[ 32 ]; fd_curve25519_scalar_mul( zz, z, z ); - fd_curve25519_scalar_mul( &scalars[ 5*32 ], zz, c ); + fd_curve25519_scalar_mul( &scalars[ 5*32 ], zz, d ); idx = 6; for( ulong i=1; itx ); fd_curve25519_scalar_sub( delta, delta, range_proof->tx ); - fd_curve25519_scalar_mul( delta, delta, c ); + fd_curve25519_scalar_mul( delta, delta, d ); fd_curve25519_scalar_muladd( &scalars[ 0 ], &scalars[ 0 ], w, delta ); /* Compute the final MSM */ + + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L415-L439 */ fd_ristretto255_multi_scalar_mul( res, scalars, points, idx ); /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L441-L445 */ From 666f3752ff14c6ed5672872e2040a1c232890033 Mon Sep 17 00:00:00 2001 From: Emanuele Cesena Date: Thu, 19 Feb 2026 17:18:21 +0000 Subject: [PATCH 7/7] zksdk: rekey and upgrade test-vectors --- .../instructions/test_fd_zksdk_pubkey_validity.h | 6 +++--- src/ballet/zksdk/transcript/fd_zksdk_transcript.h | 11 ++++++++++- src/flamenco/features/fd_features_generated.c | 6 +++--- src/flamenco/features/fd_features_generated.h | 2 +- src/flamenco/features/feature_map.json | 2 +- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/ballet/zksdk/instructions/test_fd_zksdk_pubkey_validity.h b/src/ballet/zksdk/instructions/test_fd_zksdk_pubkey_validity.h index cdf62cb34fc..4d273542d09 100644 --- a/src/ballet/zksdk/instructions/test_fd_zksdk_pubkey_validity.h +++ b/src/ballet/zksdk/instructions/test_fd_zksdk_pubkey_validity.h @@ -20,9 +20,9 @@ tx_pubkey_validity = "1b0226176edc264a8784a31e4a515baf1c76986700606d1b2924f9dc4124b8bcc412f47d158f000001000000000001" "040061" "04" // VerifyPubkeyValidity - "fa89ae0c8312aba69e727036a794b5add351b020e43c65ea94cdda8d8f8c2037" // context - "80395515497f92fa09ebdb5f14b7f6b32ab8abc3bf7349394b538fb3959c8c4b" // proof - "0e5cdb1f8f9aeb2fd374b89beafaf2f47a0b83558a7ef94629b07101f50b0007" + "8e401e07ff61abd8236f4a086c1e46b9062bc0ba8e45628dce69371d9dd4a234" // context + "bc7fe833f1b991b5344785ec2c6ab9f6fd984f4d1e5d0f0d2d5d6c1020449a7d" // proof + "ac16dfe1e004a1039f55419289a783793556f27d627bfc0f1f46f9364cbba20e" ; const ulong instr_offset_pubkey_validity = 351; diff --git a/src/ballet/zksdk/transcript/fd_zksdk_transcript.h b/src/ballet/zksdk/transcript/fd_zksdk_transcript.h index 8a90c5e46c9..9a186d44b0f 100644 --- a/src/ballet/zksdk/transcript/fd_zksdk_transcript.h +++ b/src/ballet/zksdk/transcript/fd_zksdk_transcript.h @@ -11,7 +11,6 @@ #define fd_zksdk_transcript_t fd_merlin_transcript_t #define FD_TRANSCRIPT_LITERAL FD_MERLIN_LITERAL -#define fd_zksdk_transcript_init fd_merlin_transcript_init #define fd_zksdk_transcript_append_message fd_merlin_transcript_append_message #define fd_zksdk_transcript_append_point fd_rangeproofs_transcript_append_point #define fd_zksdk_transcript_validate_and_append_point fd_rangeproofs_transcript_validate_and_append_point @@ -27,6 +26,16 @@ FD_PROTOTYPES_BEGIN - handle */ +/* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/transcript.rs#L57 */ +static inline void +fd_zksdk_transcript_init( fd_zksdk_transcript_t * transcript, + char const * const label, + uint const label_len ) { + /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/lib.rs#L36 */ + fd_merlin_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("solana-zk-elgamal-proof-program-v1") ); + fd_merlin_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("dom-sep"), (uchar *)label, label_len ); +} + static inline void fd_zksdk_transcript_append_pubkey( fd_zksdk_transcript_t * transcript, char const * const label, diff --git a/src/flamenco/features/fd_features_generated.c b/src/flamenco/features/fd_features_generated.c index 0333245f466..5ee54f2542b 100644 --- a/src/flamenco/features/fd_features_generated.c +++ b/src/flamenco/features/fd_features_generated.c @@ -1629,8 +1629,8 @@ fd_feature_id_t const ids[] = { .hardcode_for_fuzzing = 1 }, { .index = offsetof(fd_features_t, reenable_zk_elgamal_proof_program)>>3, - .id = {"\x0e\xcb\x76\xec\x8b\xf8\x21\x83\x19\x07\xc3\xb3\x5e\xc2\xd0\x13\xcb\xb4\x95\x7e\x6c\x5d\xcb\xcf\xb4\x84\xe3\xc6\xf5\x50\x7f\xbd"}, - /* zkesAyFB19sTkX8i9ReoKaMNDA4YNTPYJpZKPDt7FMW */ + .id = {"\x0e\xcb\x77\x6b\x04\xa2\x9f\x2e\x94\xf0\x15\xf1\xf4\x36\x93\xe8\xe5\x37\xb1\x87\xba\x4a\x89\xcd\x46\xcb\x0a\x41\xf7\x8f\x43\xd9"}, + /* zkexuyPRdyTVbZqEAREueqL2xvvoBhRgth9xGSc1tMN */ .name = "reenable_zk_elgamal_proof_program", .cleaned_up = 0 }, @@ -2019,7 +2019,7 @@ typedef struct fd_feature_id_lookup_entry fd_feature_id_lookup_entry_t; #define MAP_PERFECT_233 0x494f963ae12b5106UL, .val = &ids[233] #define MAP_PERFECT_234 0x210aba8db8103506UL, .val = &ids[234] #define MAP_PERFECT_235 0xec3a4c069e71cb0eUL, .val = &ids[235] -#define MAP_PERFECT_236 0x8321f88bec76cb0eUL, .val = &ids[236] +#define MAP_PERFECT_236 0x2e9fa2046b77cb0eUL, .val = &ids[236] #define MAP_PERFECT_237 0xe72f76507222e3bbUL, .val = &ids[237] #define MAP_PERFECT_238 0x7170cf84367fbb1aUL, .val = &ids[238] #define MAP_PERFECT_239 0xa9e3bfbaf8d67260UL, .val = &ids[239] diff --git a/src/flamenco/features/fd_features_generated.h b/src/flamenco/features/fd_features_generated.h index ec04be00938..eb55d62257f 100644 --- a/src/flamenco/features/fd_features_generated.h +++ b/src/flamenco/features/fd_features_generated.h @@ -252,7 +252,7 @@ union fd_features { /* 0x494f963ae12b5106 */ ulong vote_only_retransmitter_signed_fec_sets; /* 0x210aba8db8103506 */ ulong mask_out_rent_epoch_in_vm_serialization; /* 0xec3a4c069e71cb0e */ ulong disable_zk_elgamal_proof_program; - /* 0x8321f88bec76cb0e */ ulong reenable_zk_elgamal_proof_program; + /* 0x2e9fa2046b77cb0e */ ulong reenable_zk_elgamal_proof_program; /* 0xe72f76507222e3bb */ ulong formalize_loaded_transaction_data_size; /* 0x7170cf84367fbb1a */ ulong enable_extend_program_checked; /* 0xa9e3bfbaf8d67260 */ ulong require_static_nonce_account; diff --git a/src/flamenco/features/feature_map.json b/src/flamenco/features/feature_map.json index 9c1dd4c6d43..2b92b81159e 100644 --- a/src/flamenco/features/feature_map.json +++ b/src/flamenco/features/feature_map.json @@ -235,7 +235,7 @@ {"name":"vote_only_retransmitter_signed_fec_sets","pubkey":"RfEcA95xnhuwooVAhUUksEJLZBF7xKCLuqrJoqk4Zph"}, {"name":"mask_out_rent_epoch_in_vm_serialization","pubkey":"RENtePQcDLrAbxAsP3k8dwVcnNYQ466hi2uKvALjnXx","cleaned_up":1,"hardcode_for_fuzzing":1}, {"name":"disable_zk_elgamal_proof_program","pubkey":"zkdoVwnSFnSLtGJG7irJPEYUpmb4i7sGMGcnN6T9rnC","hardcode_for_fuzzing":1}, - {"name":"reenable_zk_elgamal_proof_program","pubkey":"zkesAyFB19sTkX8i9ReoKaMNDA4YNTPYJpZKPDt7FMW"}, + {"name":"reenable_zk_elgamal_proof_program","pubkey":"zkexuyPRdyTVbZqEAREueqL2xvvoBhRgth9xGSc1tMN"}, {"name":"formalize_loaded_transaction_data_size","pubkey":"DeS7sR48ZcFTUmt5FFEVDr1v1bh73aAbZiZq3SYr8Eh8","hardcode_for_fuzzing":1}, {"name":"enable_extend_program_checked","pubkey":"2oMRZEDWT2tqtYMofhmmfQ8SsjqUFzT6sYXppQDavxwz"}, {"name":"require_static_nonce_account","pubkey":"7VVhpg5oAjAmnmz1zCcSHb2Z9ecZB2FQqpnEwReka9Zm"},