From eeb0d15ea97ed506c65406635edf301eff62a6fd Mon Sep 17 00:00:00 2001 From: Shawn Xie <35279399+shawnxie999@users.noreply.github.com> Date: Wed, 11 Mar 2026 12:02:27 -0400 Subject: [PATCH] refactor: return optional buffers for helper functions (#6520) --- include/xrpl/protocol/ConfidentialTransfer.h | 65 +-- src/libxrpl/protocol/ConfidentialTransfer.cpp | 399 +++++++++++------- .../token/ConfidentialMPTClawback.cpp | 9 +- .../token/ConfidentialMPTConvert.cpp | 28 +- .../token/ConfidentialMPTConvertBack.cpp | 29 +- .../token/ConfidentialMPTMergeInbox.cpp | 15 +- .../transactors/token/ConfidentialMPTSend.cpp | 47 +-- src/test/jtx/impl/mpt.cpp | 9 +- 8 files changed, 330 insertions(+), 271 deletions(-) diff --git a/include/xrpl/protocol/ConfidentialTransfer.h b/include/xrpl/protocol/ConfidentialTransfer.h index 176d360f12..8ab7eadc32 100644 --- a/include/xrpl/protocol/ConfidentialTransfer.h +++ b/include/xrpl/protocol/ConfidentialTransfer.h @@ -25,8 +25,15 @@ namespace xrpl { */ struct ConfidentialRecipient { - Slice const publicKey; ///< The recipient's ElGamal public key (64 bytes). - Slice const encryptedAmount; ///< The encrypted amount ciphertext (128 bytes). + Slice publicKey; ///< The recipient's ElGamal public key (64 bytes). + Slice encryptedAmount; ///< The encrypted amount ciphertext (128 bytes). +}; + +/// Holds two secp256k1 public key components representing an ElGamal ciphertext (C1, C2). +struct EcPair +{ + secp256k1_pubkey c1; + secp256k1_pubkey c2; }; /** @@ -146,29 +153,25 @@ getConvertBackContextHash( * @brief Parses an ElGamal ciphertext into two secp256k1 public key components. * * Breaks a 66-byte encrypted amount (two 33-byte compressed EC points) into - * two secp256k1_pubkey structures (C1, C2) for use in cryptographic operations. + * a pair containing (C1, C2) for use in cryptographic operations. * * @param buffer The 66-byte buffer containing the compressed ciphertext. - * @param out1 Output: The C1 component of the ElGamal ciphertext. - * @param out2 Output: The C2 component of the ElGamal ciphertext. - * @return true if parsing succeeds, false if the buffer is invalid. + * @return The parsed pair (c1, c2) if successful, std::nullopt if the buffer is invalid. */ -bool -makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2); +std::optional +makeEcPair(Slice const& buffer); /** - * @brief Serializes two secp256k1 public key components into compressed form. + * @brief Serializes an EcPair into compressed form. * - * Converts two secp256k1_pubkey structures (C1, C2) back into a 66-byte - * buffer containing two 33-byte compressed EC points. + * Converts an EcPair (C1, C2) back into a 66-byte buffer containing + * two 33-byte compressed EC points. * - * @param in1 The C1 component to serialize. - * @param in2 The C2 component to serialize. - * @param buffer Output: The 66-byte buffer to write the compressed ciphertext. - * @return true if serialization succeeds, false otherwise. + * @param pair The EcPair to serialize. + * @return The 66-byte buffer, or std::nullopt if serialization fails. */ -bool -serializeEcPair(secp256k1_pubkey const& in1, secp256k1_pubkey const& in2, Buffer& buffer); +std::optional +serializeEcPair(EcPair const& pair); /** * @brief Verifies that a buffer contains two valid, parsable EC public keys. @@ -197,13 +200,12 @@ isValidCompressedECPoint(Slice const& buffer); * Uses the additive homomorphic property of ElGamal encryption to compute * Enc(a + b) from Enc(a) and Enc(b) without decryption. * - * @param a The first ciphertext (66 bytes). - * @param b The second ciphertext (66 bytes). - * @param out Output: The resulting ciphertext Enc(a + b). - * @return tesSUCCESS on success, or an error code if parsing fails. + * @param a The first ciphertext (66 bytes). + * @param b The second ciphertext (66 bytes). + * @return The resulting ciphertext Enc(a + b), or std::nullopt on failure. */ -TER -homomorphicAdd(Slice const& a, Slice const& b, Buffer& out); +std::optional +homomorphicAdd(Slice const& a, Slice const& b); /** * @brief Homomorphically subtracts two ElGamal ciphertexts. @@ -211,13 +213,12 @@ homomorphicAdd(Slice const& a, Slice const& b, Buffer& out); * Uses the additive homomorphic property of ElGamal encryption to compute * Enc(a - b) from Enc(a) and Enc(b) without decryption. * - * @param a The minuend ciphertext (66 bytes). - * @param b The subtrahend ciphertext (66 bytes). - * @param out Output: The resulting ciphertext Enc(a - b). - * @return tesSUCCESS on success, or an error code if parsing fails. + * @param a The minuend ciphertext (66 bytes). + * @param b The subtrahend ciphertext (66 bytes). + * @return The resulting ciphertext Enc(a - b), or std::nullopt on failure. */ -TER -homomorphicSubtract(Slice const& a, Slice const& b, Buffer& out); +std::optional +homomorphicSubtract(Slice const& a, Slice const& b); /** * @brief Encrypts an amount using ElGamal encryption. @@ -275,7 +276,7 @@ verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 co */ TER verifyElGamalEncryption( - std::uint64_t const amount, + uint64_t const amount, Slice const& blindingFactor, Slice const& pubKeySlice, Slice const& ciphertext); @@ -309,7 +310,7 @@ checkEncryptedAmountFormat(STObject const& object); */ TER verifyRevealedAmount( - std::uint64_t const amount, + uint64_t const amount, Slice const& blindingFactor, ConfidentialRecipient const& holder, ConfidentialRecipient const& issuer, @@ -479,5 +480,5 @@ computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitme * @return tesSUCCESS on success, tecINTERNAL on failure or if amount is 0. */ TER -computeConvertBackRemainder(Slice const& commitment, std::uint64_t amount, Buffer& out); +computeConvertBackRemainder(Slice const& commitment, uint64_t amount, Buffer& out); } // namespace xrpl diff --git a/src/libxrpl/protocol/ConfidentialTransfer.cpp b/src/libxrpl/protocol/ConfidentialTransfer.cpp index e037e68e67..0b2b9b0c99 100644 --- a/src/libxrpl/protocol/ConfidentialTransfer.cpp +++ b/src/libxrpl/protocol/ConfidentialTransfer.cpp @@ -87,11 +87,11 @@ getConvertBackContextHash( return s.getSHA512Half(); } -bool -makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2) +std::optional +makeEcPair(Slice const& buffer) { if (buffer.length() != 2 * ecGamalEncryptedLength) - return false; // LCOV_EXCL_LINE + return std::nullopt; // LCOV_EXCL_LINE auto parsePubKey = [](Slice const& slice, secp256k1_pubkey& out) { return secp256k1_ec_pubkey_parse( @@ -104,14 +104,15 @@ makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2) Slice s1{buffer.data(), ecGamalEncryptedLength}; Slice s2{buffer.data() + ecGamalEncryptedLength, ecGamalEncryptedLength}; - int const ret1 = parsePubKey(s1, out1); - int const ret2 = parsePubKey(s2, out2); + EcPair pair; + if (parsePubKey(s1, pair.c1) != 1 || parsePubKey(s2, pair.c2) != 1) + return std::nullopt; - return ret1 == 1 && ret2 == 1; + return pair; } -bool -serializeEcPair(secp256k1_pubkey const& in1, secp256k1_pubkey const& in2, Buffer& buffer) +std::optional +serializeEcPair(EcPair const& pair) { auto serializePubKey = [](secp256k1_pubkey const& pub, unsigned char* out) { size_t outLen = ecGamalEncryptedLength; // 33 bytes @@ -120,19 +121,21 @@ serializeEcPair(secp256k1_pubkey const& in1, secp256k1_pubkey const& in2, Buffer return ret == 1 && outLen == ecGamalEncryptedLength; }; + Buffer buffer(ecGamalEncryptedTotalLength); unsigned char* ptr = buffer.data(); - bool const res1 = serializePubKey(in1, ptr); - bool const res2 = serializePubKey(in2, ptr + ecGamalEncryptedLength); + bool const res1 = serializePubKey(pair.c1, ptr); + bool const res2 = serializePubKey(pair.c2, ptr + ecGamalEncryptedLength); - return res1 && res2; + if (!res1 || !res2) + return std::nullopt; + + return buffer; } bool isValidCiphertext(Slice const& buffer) { - secp256k1_pubkey key1; - secp256k1_pubkey key2; - return makeEcPair(buffer, key1, key2); + return makeEcPair(buffer).has_value(); } bool @@ -149,57 +152,50 @@ isValidCompressedECPoint(Slice const& buffer) return secp256k1_ec_pubkey_parse(secp256k1Context(), &point, buffer.data(), buffer.size()) == 1; } -TER -homomorphicAdd(Slice const& a, Slice const& b, Buffer& out) +std::optional +homomorphicAdd(Slice const& a, Slice const& b) { if (a.length() != ecGamalEncryptedTotalLength || b.length() != ecGamalEncryptedTotalLength) - return tecINTERNAL; + return std::nullopt; - secp256k1_pubkey aC1; - secp256k1_pubkey aC2; - secp256k1_pubkey bC1; - secp256k1_pubkey bC2; + auto const pairA = makeEcPair(a); + auto const pairB = makeEcPair(b); - if (!makeEcPair(a, aC1, aC2) || !makeEcPair(b, bC1, bC2)) - return tecINTERNAL; + if (!pairA || !pairB) + return std::nullopt; - secp256k1_pubkey sumC1; - secp256k1_pubkey sumC2; + EcPair sum; + if (auto res = secp256k1_elgamal_add( + secp256k1Context(), &sum.c1, &sum.c2, &pairA->c1, &pairA->c2, &pairB->c1, &pairB->c2); + res != 1) + { + return std::nullopt; + } - if (secp256k1_elgamal_add(secp256k1Context(), &sumC1, &sumC2, &aC1, &aC2, &bC1, &bC2) != 1) - return tecINTERNAL; - - if (!serializeEcPair(sumC1, sumC2, out)) - return tecINTERNAL; - - return tesSUCCESS; + return serializeEcPair(sum); } -TER -homomorphicSubtract(Slice const& a, Slice const& b, Buffer& out) +std::optional +homomorphicSubtract(Slice const& a, Slice const& b) { if (a.length() != ecGamalEncryptedTotalLength || b.length() != ecGamalEncryptedTotalLength) - return tecINTERNAL; + return std::nullopt; - secp256k1_pubkey aC1; - secp256k1_pubkey aC2; - secp256k1_pubkey bC1; - secp256k1_pubkey bC2; + auto const pairA = makeEcPair(a); + auto const pairB = makeEcPair(b); - if (!makeEcPair(a, aC1, aC2) || !makeEcPair(b, bC1, bC2)) - return tecINTERNAL; + if (!pairA || !pairB) + return std::nullopt; - secp256k1_pubkey diffC1; - secp256k1_pubkey diffC2; + EcPair diff; + if (auto res = secp256k1_elgamal_subtract( + secp256k1Context(), &diff.c1, &diff.c2, &pairA->c1, &pairA->c2, &pairB->c1, &pairB->c2); + res != 1) + { + return std::nullopt; + } - if (secp256k1_elgamal_subtract(secp256k1Context(), &diffC1, &diffC2, &aC1, &aC2, &bC1, &bC2) != - 1) - return tecINTERNAL; - - if (!serializeEcPair(diffC1, diffC2, out)) - return tecINTERNAL; - - return tesSUCCESS; + return serializeEcPair(diff); } Buffer @@ -223,20 +219,23 @@ encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindin if (pubKeySlice.size() != ecPubKeyLength) return std::nullopt; - secp256k1_pubkey c1, c2, pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + EcPair pair; + secp256k1_pubkey pubKey; + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { return std::nullopt; + } - if (!secp256k1_elgamal_encrypt( - secp256k1Context(), &c1, &c2, &pubKey, amt, blindingFactor.data())) + if (auto res = secp256k1_elgamal_encrypt( + secp256k1Context(), &pair.c1, &pair.c2, &pubKey, amt, blindingFactor.data()); + res != 1) + { return std::nullopt; + } - Buffer buf(ecGamalEncryptedTotalLength); - if (!serializeEcPair(c1, c2, buf)) - return std::nullopt; - - return buf; + return serializeEcPair(pair); } std::optional @@ -245,20 +244,23 @@ encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, M if (pubKeySlice.size() != ecPubKeyLength) return std::nullopt; // LCOV_EXCL_LINE - secp256k1_pubkey c1, c2, pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + EcPair pair; + secp256k1_pubkey pubKey; + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { return std::nullopt; // LCOV_EXCL_LINE + } - if (!generate_canonical_encrypted_zero( - secp256k1Context(), &c1, &c2, &pubKey, account.data(), mptId.data())) + if (auto res = generate_canonical_encrypted_zero( + secp256k1Context(), &pair.c1, &pair.c2, &pubKey, account.data(), mptId.data()); + res != 1) + { return std::nullopt; // LCOV_EXCL_LINE + } - Buffer buf(ecGamalEncryptedTotalLength); - if (!serializeEcPair(c1, c2, buf)) - return std::nullopt; // LCOV_EXCL_LINE - - return buf; + return serializeEcPair(pair); } TER @@ -271,20 +273,26 @@ verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 co return tecINTERNAL; // LCOV_EXCL_LINE secp256k1_pubkey pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } - if (secp256k1_mpt_pok_sk_verify( - secp256k1Context(), proofSlice.data(), &pubKey, contextHash.data()) != 1) + if (auto res = secp256k1_mpt_pok_sk_verify( + secp256k1Context(), proofSlice.data(), &pubKey, contextHash.data()); + res != 1) + { return tecBAD_PROOF; + } return tesSUCCESS; } TER verifyElGamalEncryption( - std::uint64_t const amount, + uint64_t const amount, Slice const& blindingFactor, Slice const& pubKeySlice, Slice const& ciphertext) @@ -294,24 +302,30 @@ verifyElGamalEncryption( return tecINTERNAL; // LCOV_EXCL_LINE secp256k1_pubkey pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { + return tecINTERNAL; // LCOV_EXCL_LINE + } + + auto const pair = makeEcPair(ciphertext); + if (!pair) return tecINTERNAL; // LCOV_EXCL_LINE - secp256k1_pubkey c1, c2; - if (!makeEcPair(ciphertext, c1, c2)) - return tecINTERNAL; // LCOV_EXCL_LINE - - if (secp256k1_elgamal_verify_encryption( - secp256k1Context(), &c1, &c2, &pubKey, amount, blindingFactor.data()) != 1) + if (auto res = secp256k1_elgamal_verify_encryption( + secp256k1Context(), &pair->c1, &pair->c2, &pubKey, amount, blindingFactor.data()); + res != 1) + { return tecBAD_PROOF; + } return tesSUCCESS; } TER verifyRevealedAmount( - std::uint64_t const amount, + uint64_t const amount, Slice const& blindingFactor, ConfidentialRecipient const& holder, ConfidentialRecipient const& issuer, @@ -376,9 +390,12 @@ verifyMultiCiphertextEqualityProof( // Parse Shared C1 from the first recipient only if (i == 0) { - if (!secp256k1_ec_pubkey_parse( - ctx, &c1, recipient.encryptedAmount.data(), ecGamalEncryptedLength)) + if (auto res = secp256k1_ec_pubkey_parse( + ctx, &c1, recipient.encryptedAmount.data(), ecGamalEncryptedLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } } else { @@ -392,25 +409,30 @@ verifyMultiCiphertextEqualityProof( } } - if (secp256k1_ec_pubkey_parse( + if (auto res = secp256k1_ec_pubkey_parse( ctx, &c2_vec[i], recipient.encryptedAmount.data() + ecGamalEncryptedLength, - ecGamalEncryptedLength) != 1) + ecGamalEncryptedLength); + res != 1) { return tecINTERNAL; // LCOV_EXCL_LINE } - if (secp256k1_ec_pubkey_parse( - ctx, &pk_vec[i], recipient.publicKey.data(), ecPubKeyLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + ctx, &pk_vec[i], recipient.publicKey.data(), ecPubKeyLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } } - int const result = secp256k1_mpt_verify_equality_shared_r( - ctx, proof.data(), nRecipients, &c1, c2_vec.data(), pk_vec.data(), contextHash.data()); - - if (result != 1) + if (auto res = secp256k1_mpt_verify_equality_shared_r( + ctx, proof.data(), nRecipients, &c1, c2_vec.data(), pk_vec.data(), contextHash.data()); + res != 1) + { return tecBAD_PROOF; + } return tesSUCCESS; } @@ -427,20 +449,30 @@ verifyClawbackEqualityProof( proof.size() != ecEqualityProofLength) return tecINTERNAL; // LCOV_EXCL_LINE - secp256k1_pubkey c1, c2; - if (!makeEcPair(ciphertext, c1, c2)) + auto const pair = makeEcPair(ciphertext); + if (!pair) return tecINTERNAL; // LCOV_EXCL_LINE secp256k1_pubkey pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } // Note: c2, c1 order - the proof is generated with c2 first (the encrypted // message component) because the equality proof structure expects the // message-containing term before the blinding term. - if (secp256k1_equality_plaintext_verify( - secp256k1Context(), proof.data(), &pubKey, &c2, &c1, amount, contextHash.data()) != 1) + if (auto res = secp256k1_equality_plaintext_verify( + secp256k1Context(), + proof.data(), + &pubKey, + &pair->c2, + &pair->c1, + amount, + contextHash.data()); + res != 1) { return tecBAD_PROOF; } @@ -487,8 +519,8 @@ verifyAmountPcmLinkage( if (proof.length() != ecPedersenProofLength) return tecINTERNAL; - secp256k1_pubkey c1, c2; - if (!makeEcPair(encAmt, c1, c2)) + auto const pair = makeEcPair(encAmt); + if (!pair) return tecINTERNAL; // LCOV_EXCL_LINE if (pubKeySlice.size() != ecPubKeyLength) @@ -498,17 +530,30 @@ verifyAmountPcmLinkage( return tecINTERNAL; // LCOV_EXCL_LINE secp256k1_pubkey pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } secp256k1_pubkey pcm; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } - if (secp256k1_elgamal_pedersen_link_verify( - secp256k1Context(), proof.data(), &c1, &c2, &pubKey, &pcm, contextHash.data()) != 1) + if (auto res = secp256k1_elgamal_pedersen_link_verify( + secp256k1Context(), + proof.data(), + &pair->c1, + &pair->c2, + &pubKey, + &pcm, + contextHash.data()); + res != 1) { return tecBAD_PROOF; } @@ -527,10 +572,8 @@ verifyBalancePcmLinkage( if (proof.length() != ecPedersenProofLength) return tecINTERNAL; - secp256k1_pubkey c1; - secp256k1_pubkey c2; - - if (!makeEcPair(encAmt, c1, c2)) + auto const pair = makeEcPair(encAmt); + if (!pair) return tecINTERNAL; // LCOV_EXCL_LINE if (pubKeySlice.size() != ecPubKeyLength) @@ -540,19 +583,32 @@ verifyBalancePcmLinkage( return tecINTERNAL; // LCOV_EXCL_LINE secp256k1_pubkey pubKey; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } secp256k1_pubkey pcm; - if (secp256k1_ec_pubkey_parse( - secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } // Note: c2, c1 order - the linkage proof expects the message-containing // component (c2 = m*G + r*Pk) before the blinding component (c1 = r*G). - if (secp256k1_elgamal_pedersen_link_verify( - secp256k1Context(), proof.data(), &pubKey, &c2, &c1, &pcm, contextHash.data()) != 1) + if (auto res = secp256k1_elgamal_pedersen_link_verify( + secp256k1Context(), + proof.data(), + &pubKey, + &pair->c2, + &pair->c1, + &pcm, + contextHash.data()); + res != 1) { return tecBAD_PROOF; } @@ -586,12 +642,12 @@ verifyAggregatedBulletproof( if (compressedCommitments[i].size() != ecPedersenCommitmentLength) return tecINTERNAL; // LCOV_EXCL_LINE - if (secp256k1_ec_pubkey_parse( - ctx, - &commitments[i], - compressedCommitments[i].data(), - ecPedersenCommitmentLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + ctx, &commitments[i], compressedCommitments[i].data(), ecPedersenCommitmentLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } } // 3. Prepare Generator Vectors (G_vec, H_vec) @@ -601,37 +657,42 @@ verifyAggregatedBulletproof( std::vector H_vec(n); // Retrieve deterministic generators "G" and "H" - if (secp256k1_mpt_get_generator_vector(ctx, G_vec.data(), n, (unsigned char const*)"G", 1) != 1) + if (auto res = + secp256k1_mpt_get_generator_vector(ctx, G_vec.data(), n, (unsigned char const*)"G", 1); + res != 1) { return tecINTERNAL; // LCOV_EXCL_LINE } - if (secp256k1_mpt_get_generator_vector(ctx, H_vec.data(), n, (unsigned char const*)"H", 1) != 1) + if (auto res = + secp256k1_mpt_get_generator_vector(ctx, H_vec.data(), n, (unsigned char const*)"H", 1); + res != 1) { return tecINTERNAL; // LCOV_EXCL_LINE } // 4. Prepare Base Generator (pk_base / H) secp256k1_pubkey pk_base; - if (secp256k1_mpt_get_h_generator(ctx, &pk_base) != 1) + if (auto res = secp256k1_mpt_get_h_generator(ctx, &pk_base); res != 1) { return tecINTERNAL; // LCOV_EXCL_LINE } // 5. Verify the Proof - int const result = secp256k1_bulletproof_verify_agg( - ctx, - G_vec.data(), - H_vec.data(), - reinterpret_cast(proof.data()), - proof.size(), - commitments.data(), - m, - &pk_base, - contextHash.data()); - - if (result != 1) + if (auto res = secp256k1_bulletproof_verify_agg( + ctx, + G_vec.data(), + H_vec.data(), + reinterpret_cast(proof.data()), + proof.size(), + commitments.data(), + m, + &pk_base, + contextHash.data()); + res != 1) + { return tecBAD_PROOF; + } return tesSUCCESS; } @@ -646,37 +707,50 @@ computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitme auto const ctx = secp256k1Context(); secp256k1_pubkey pcBalance; - if (secp256k1_ec_pubkey_parse( - ctx, &pcBalance, balanceCommitment.data(), ecPedersenCommitmentLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + ctx, &pcBalance, balanceCommitment.data(), ecPedersenCommitmentLength); + res != 1) + { return tecINTERNAL; + } secp256k1_pubkey pcAmount; - if (secp256k1_ec_pubkey_parse( - ctx, &pcAmount, amountCommitment.data(), ecPedersenCommitmentLength) != 1) + if (auto res = secp256k1_ec_pubkey_parse( + ctx, &pcAmount, amountCommitment.data(), ecPedersenCommitmentLength); + res != 1) + { return tecINTERNAL; + } // Negate PC_amount point to get -PC_amount - if (!secp256k1_ec_pubkey_negate(ctx, &pcAmount)) + if (auto res = secp256k1_ec_pubkey_negate(ctx, &pcAmount); res != 1) + { return tecINTERNAL; + } // Compute pcRem = pcBalance + (-pcAmount) secp256k1_pubkey const* summands[2] = {&pcBalance, &pcAmount}; secp256k1_pubkey pcRem; - if (!secp256k1_ec_pubkey_combine(ctx, &pcRem, summands, 2)) + if (auto res = secp256k1_ec_pubkey_combine(ctx, &pcRem, summands, 2); res != 1) + { return tecINTERNAL; + } // Serialize result to compressed format out.alloc(ecPedersenCommitmentLength); size_t outLen = ecPedersenCommitmentLength; - if (secp256k1_ec_pubkey_serialize(ctx, out.data(), &outLen, &pcRem, SECP256K1_EC_COMPRESSED) != - 1) + if (auto res = secp256k1_ec_pubkey_serialize( + ctx, out.data(), &outLen, &pcRem, SECP256K1_EC_COMPRESSED); + res != 1) + { return tecINTERNAL; + } return tesSUCCESS; } TER -computeConvertBackRemainder(Slice const& commitment, std::uint64_t amount, Buffer& out) +computeConvertBackRemainder(Slice const& commitment, uint64_t amount, Buffer& out) { if (commitment.size() != ecPedersenCommitmentLength || amount == 0) return tecINTERNAL; // LCOV_EXCL_LINE @@ -685,37 +759,48 @@ computeConvertBackRemainder(Slice const& commitment, std::uint64_t amount, Buffe // Parse commitment from compressed format secp256k1_pubkey pcBalance; - if (secp256k1_ec_pubkey_parse(ctx, &pcBalance, commitment.data(), ecPedersenCommitmentLength) != - 1) + if (auto res = secp256k1_ec_pubkey_parse( + ctx, &pcBalance, commitment.data(), ecPedersenCommitmentLength); + res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } // Convert amount to 32-byte big-endian scalar unsigned char mScalar[32] = {0}; - std::uint64_t amountBigEndian = boost::endian::native_to_big(amount); + uint64_t amountBigEndian = boost::endian::native_to_big(amount); std::memcpy(&mScalar[24], &amountBigEndian, sizeof(amountBigEndian)); // Compute mG = amount * G secp256k1_pubkey mG; - if (!secp256k1_ec_pubkey_create(ctx, &mG, mScalar)) + if (auto res = secp256k1_ec_pubkey_create(ctx, &mG, mScalar); res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } // Negate mG to get -mG - if (!secp256k1_ec_pubkey_negate(ctx, &mG)) + if (auto res = secp256k1_ec_pubkey_negate(ctx, &mG); res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } // Compute pcRem = pcBalance + (-mG) secp256k1_pubkey const* summands[2] = {&pcBalance, &mG}; secp256k1_pubkey pcRem; - if (!secp256k1_ec_pubkey_combine(ctx, &pcRem, summands, 2)) + if (auto res = secp256k1_ec_pubkey_combine(ctx, &pcRem, summands, 2); res != 1) + { return tecINTERNAL; // LCOV_EXCL_LINE + } // Serialize result to compressed format out.alloc(ecPedersenCommitmentLength); size_t outLen = ecPedersenCommitmentLength; - if (secp256k1_ec_pubkey_serialize(ctx, out.data(), &outLen, &pcRem, SECP256K1_EC_COMPRESSED) != - 1 || - outLen != ecPedersenCommitmentLength) + if (auto res = secp256k1_ec_pubkey_serialize( + ctx, out.data(), &outLen, &pcRem, SECP256K1_EC_COMPRESSED); + res != 1 || outLen != ecPedersenCommitmentLength) + { return tecINTERNAL; // LCOV_EXCL_LINE + } return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp index f29ee67550..46174841fa 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp @@ -117,14 +117,14 @@ ConfidentialMPTClawback::doApply() if (!encZeroForHolder) return tecINTERNAL; // LCOV_EXCL_LINE - auto const encZeroForIssuer = encryptCanonicalZeroAmount(issuerPubKey, holder, mptIssuanceID); + auto encZeroForIssuer = encryptCanonicalZeroAmount(issuerPubKey, holder, mptIssuanceID); if (!encZeroForIssuer) return tecINTERNAL; // LCOV_EXCL_LINE // Set holder's confidential balances to encrypted zero (*sleHolderMPToken)[sfConfidentialBalanceInbox] = *encZeroForHolder; (*sleHolderMPToken)[sfConfidentialBalanceSpending] = *encZeroForHolder; - (*sleHolderMPToken)[sfIssuerEncryptedBalance] = *encZeroForIssuer; + (*sleHolderMPToken)[sfIssuerEncryptedBalance] = std::move(*encZeroForIssuer); incrementConfidentialVersion(*sleHolderMPToken); if (sleHolderMPToken->isFieldPresent(sfAuditorEncryptedBalance)) @@ -136,13 +136,12 @@ ConfidentialMPTClawback::doApply() Slice const auditorPubKey = (*sleIssuance)[sfAuditorElGamalPublicKey]; - auto const encZeroForAuditor = - encryptCanonicalZeroAmount(auditorPubKey, holder, mptIssuanceID); + auto encZeroForAuditor = encryptCanonicalZeroAmount(auditorPubKey, holder, mptIssuanceID); if (!encZeroForAuditor) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleHolderMPToken)[sfAuditorEncryptedBalance] = *encZeroForAuditor; + (*sleHolderMPToken)[sfAuditorEncryptedBalance] = std::move(*encZeroForAuditor); } // Decrease Global Confidential Outstanding Amount diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp index 548e6ddc00..4b86b34bb4 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp @@ -189,36 +189,30 @@ ConfidentialMPTConvert::doApply() { // Case 1: Add to existing inbox balance (holder will merge later) { - Buffer sum(ecGamalEncryptedTotalLength); - if (TER const ter = - homomorphicAdd(holderEc, (*sleMptoken)[sfConfidentialBalanceInbox], sum); - !isTesSuccess(ter)) + auto sum = homomorphicAdd(holderEc, (*sleMptoken)[sfConfidentialBalanceInbox]); + if (!sum) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfConfidentialBalanceInbox] = sum; + (*sleMptoken)[sfConfidentialBalanceInbox] = std::move(*sum); } // homomorphically add issuer's encrypted balance { - Buffer sum(ecGamalEncryptedTotalLength); - if (TER const ter = - homomorphicAdd(issuerEc, (*sleMptoken)[sfIssuerEncryptedBalance], sum); - !isTesSuccess(ter)) + auto sum = homomorphicAdd(issuerEc, (*sleMptoken)[sfIssuerEncryptedBalance]); + if (!sum) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfIssuerEncryptedBalance] = sum; + (*sleMptoken)[sfIssuerEncryptedBalance] = std::move(*sum); } // homomorphically add auditor's encrypted balance if (auditorEc) { - Buffer sum(ecGamalEncryptedTotalLength); - if (TER const ter = - homomorphicAdd(*auditorEc, (*sleMptoken)[sfAuditorEncryptedBalance], sum); - !isTesSuccess(ter)) + auto sum = homomorphicAdd(*auditorEc, (*sleMptoken)[sfAuditorEncryptedBalance]); + if (!sum) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfAuditorEncryptedBalance] = sum; + (*sleMptoken)[sfAuditorEncryptedBalance] = std::move(*sum); } } else if ( @@ -236,13 +230,13 @@ ConfidentialMPTConvert::doApply() // Spending balance starts at zero. Must use canonical zero encryption // (deterministic ciphertext) so the ledger state is reproducible. - auto const zeroBalance = encryptCanonicalZeroAmount( + auto zeroBalance = encryptCanonicalZeroAmount( (*sleMptoken)[sfHolderElGamalPublicKey], account_, mptIssuanceID); if (!zeroBalance) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfConfidentialBalanceSpending] = *zeroBalance; + (*sleMptoken)[sfConfidentialBalanceSpending] = std::move(*zeroBalance); } else { diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp index b01477694c..6776a89c17 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp @@ -256,37 +256,32 @@ ConfidentialMPTConvertBack::doApply() // homomorphically subtract holder's encrypted balance { - Buffer res(ecGamalEncryptedTotalLength); - if (TER const ter = homomorphicSubtract( - (*sleMptoken)[sfConfidentialBalanceSpending], - ctx_.tx[sfHolderEncryptedAmount], - res); - !isTesSuccess(ter)) + auto res = homomorphicSubtract( + (*sleMptoken)[sfConfidentialBalanceSpending], ctx_.tx[sfHolderEncryptedAmount]); + if (!res) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfConfidentialBalanceSpending] = res; + (*sleMptoken)[sfConfidentialBalanceSpending] = std::move(*res); } // homomorphically subtract issuer's encrypted balance { - Buffer res(ecGamalEncryptedTotalLength); - if (TER const ter = homomorphicSubtract( - (*sleMptoken)[sfIssuerEncryptedBalance], ctx_.tx[sfIssuerEncryptedAmount], res); - !isTesSuccess(ter)) + auto res = homomorphicSubtract( + (*sleMptoken)[sfIssuerEncryptedBalance], ctx_.tx[sfIssuerEncryptedAmount]); + if (!res) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfIssuerEncryptedBalance] = res; + (*sleMptoken)[sfIssuerEncryptedBalance] = std::move(*res); } if (auditorEc) { - Buffer res(ecGamalEncryptedTotalLength); - if (TER const ter = homomorphicSubtract( - (*sleMptoken)[sfAuditorEncryptedBalance], ctx_.tx[sfAuditorEncryptedAmount], res); - !isTesSuccess(ter)) + auto res = homomorphicSubtract( + (*sleMptoken)[sfAuditorEncryptedBalance], ctx_.tx[sfAuditorEncryptedAmount]); + if (!res) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfAuditorEncryptedBalance] = res; + (*sleMptoken)[sfAuditorEncryptedBalance] = std::move(*res); } incrementConfidentialVersion(*sleMptoken); diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp index d7414dbb78..f69191ae07 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp @@ -68,25 +68,22 @@ ConfidentialMPTMergeInbox::doApply() // Merge inbox into spending: spending = spending + inbox // This allows holder to use received funds. Without merging, incoming // transfers sit in inbox and cannot be spent or converted back. - Buffer sum(ecGamalEncryptedTotalLength); - if (TER const ter = homomorphicAdd( - (*sleMptoken)[sfConfidentialBalanceSpending], - (*sleMptoken)[sfConfidentialBalanceInbox], - sum); - !isTesSuccess(ter)) + auto sum = homomorphicAdd( + (*sleMptoken)[sfConfidentialBalanceSpending], (*sleMptoken)[sfConfidentialBalanceInbox]); + if (!sum) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfConfidentialBalanceSpending] = sum; + (*sleMptoken)[sfConfidentialBalanceSpending] = std::move(*sum); // Reset inbox to encrypted zero. Must use canonical zero encryption // (deterministic ciphertext) so the ledger state is reproducible. - auto const zeroEncryption = encryptCanonicalZeroAmount( + auto zeroEncryption = encryptCanonicalZeroAmount( (*sleMptoken)[sfHolderElGamalPublicKey], account_, mptIssuanceID); if (!zeroEncryption) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleMptoken)[sfConfidentialBalanceInbox] = *zeroEncryption; + (*sleMptoken)[sfConfidentialBalanceInbox] = std::move(*zeroEncryption); incrementConfidentialVersion(*sleMptoken); diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp index bf3672933d..d89b8959d5 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp @@ -338,74 +338,63 @@ ConfidentialMPTSend::doApply() // Subtract from sender's spending balance { Slice const curSpending = (*sleSenderMPToken)[sfConfidentialBalanceSpending]; - Buffer newSpending(ecGamalEncryptedTotalLength); - - if (TER const ter = homomorphicSubtract(curSpending, senderEc, newSpending); - !isTesSuccess(ter)) + auto newSpending = homomorphicSubtract(curSpending, senderEc); + if (!newSpending) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleSenderMPToken)[sfConfidentialBalanceSpending] = newSpending; + (*sleSenderMPToken)[sfConfidentialBalanceSpending] = std::move(*newSpending); } // Subtract from issuer's balance { Slice const curIssuerEnc = (*sleSenderMPToken)[sfIssuerEncryptedBalance]; - Buffer newIssuerEnc(ecGamalEncryptedTotalLength); - - if (TER const ter = homomorphicSubtract(curIssuerEnc, issuerEc, newIssuerEnc); - !isTesSuccess(ter)) + auto newIssuerEnc = homomorphicSubtract(curIssuerEnc, issuerEc); + if (!newIssuerEnc) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleSenderMPToken)[sfIssuerEncryptedBalance] = newIssuerEnc; + (*sleSenderMPToken)[sfIssuerEncryptedBalance] = std::move(*newIssuerEnc); } // Subtract from auditor's balance if present if (auditorEc) { Slice const curAuditorEnc = (*sleSenderMPToken)[sfAuditorEncryptedBalance]; - Buffer newAuditorEnc(ecGamalEncryptedTotalLength); - - if (TER const ter = homomorphicSubtract(curAuditorEnc, *auditorEc, newAuditorEnc); - !isTesSuccess(ter)) + auto newAuditorEnc = homomorphicSubtract(curAuditorEnc, *auditorEc); + if (!newAuditorEnc) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleSenderMPToken)[sfAuditorEncryptedBalance] = newAuditorEnc; + (*sleSenderMPToken)[sfAuditorEncryptedBalance] = std::move(*newAuditorEnc); } // Add to destination's inbox balance { Slice const curInbox = (*sleDestinationMPToken)[sfConfidentialBalanceInbox]; - Buffer newInbox(ecGamalEncryptedTotalLength); - - if (TER const ter = homomorphicAdd(curInbox, destEc, newInbox); !isTesSuccess(ter)) + auto newInbox = homomorphicAdd(curInbox, destEc); + if (!newInbox) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleDestinationMPToken)[sfConfidentialBalanceInbox] = newInbox; + (*sleDestinationMPToken)[sfConfidentialBalanceInbox] = std::move(*newInbox); } // Add to issuer's balance { Slice const curIssuerEnc = (*sleDestinationMPToken)[sfIssuerEncryptedBalance]; - Buffer newIssuerEnc(ecGamalEncryptedTotalLength); - - if (TER const ter = homomorphicAdd(curIssuerEnc, issuerEc, newIssuerEnc); - !isTesSuccess(ter)) + auto newIssuerEnc = homomorphicAdd(curIssuerEnc, issuerEc); + if (!newIssuerEnc) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleDestinationMPToken)[sfIssuerEncryptedBalance] = newIssuerEnc; + (*sleDestinationMPToken)[sfIssuerEncryptedBalance] = std::move(*newIssuerEnc); } // Add to auditor's balance if present if (auditorEc) { Slice const curAuditorEnc = (*sleDestinationMPToken)[sfAuditorEncryptedBalance]; - Buffer newAuditorEnc(ecGamalEncryptedTotalLength); - - if (TER const ter = homomorphicAdd(curAuditorEnc, *auditorEc, newAuditorEnc); - !isTesSuccess(ter)) + auto newAuditorEnc = homomorphicAdd(curAuditorEnc, *auditorEc); + if (!newAuditorEnc) return tecINTERNAL; // LCOV_EXCL_LINE - (*sleDestinationMPToken)[sfAuditorEncryptedBalance] = newAuditorEnc; + (*sleDestinationMPToken)[sfAuditorEncryptedBalance] = std::move(*newAuditorEnc); } // increment sender version only; receiver version is not modified by incoming sends diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index 629daad23d..38026d0c1b 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -1629,10 +1629,8 @@ MPTTester::decryptAmount(Account const& account, Buffer const& amt) const if (amt.size() != ecGamalEncryptedTotalLength) return std::nullopt; - secp256k1_pubkey c1; - secp256k1_pubkey c2; - - if (!makeEcPair(amt, c1, c2)) + auto const pair = makeEcPair(amt); + if (!pair) return std::nullopt; auto const privKey = getPrivKey(account); @@ -1640,7 +1638,8 @@ MPTTester::decryptAmount(Account const& account, Buffer const& amt) const return std::nullopt; uint64_t decryptedAmt; - if (!secp256k1_elgamal_decrypt(secp256k1Context(), &decryptedAmt, &c1, &c2, privKey->data())) + if (!secp256k1_elgamal_decrypt( + secp256k1Context(), &decryptedAmt, &pair->c1, &pair->c2, privKey->data())) { return std::nullopt; }