update sfBlindingFactor to type uint256 and refactor helper functions to return std::optional

This commit is contained in:
Shawn Xie
2026-03-19 14:04:03 -04:00
committed by GitHub
parent 9f4cf28aea
commit a43cf94ff7
10 changed files with 108 additions and 111 deletions

View File

@@ -25,8 +25,9 @@ namespace xrpl {
*/
struct ConfidentialRecipient
{
Slice publicKey; ///< The recipient's ElGamal public key (64 bytes).
Slice encryptedAmount; ///< The encrypted amount ciphertext (128 bytes).
Slice publicKey; ///< The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
Slice encryptedAmount; ///< The encrypted amount ciphertext
///< (size=xrpl::ecGamalEncryptedTotalLength).
};
/// Holds two secp256k1 public key components representing an ElGamal ciphertext (C1, C2).
@@ -73,8 +74,8 @@ addCommonZKPFields(
Serializer& s,
std::uint16_t txType,
AccountID const& account,
std::uint32_t sequence,
uint192 const& issuanceID);
uint192 const& issuanceID,
std::uint32_t sequence);
/**
* @brief Generates the context hash for ConfidentialMPTSend transactions.
@@ -227,9 +228,10 @@ homomorphicSubtract(Slice const& a, Slice const& b);
* using the provided blinding factor r.
*
* @param amt The plaintext amount to encrypt.
* @param pubKeySlice The recipient's ElGamal public key (64 bytes).
* @param blindingFactor The 32-byte randomness used as blinding factor r.
* @return The 66-byte ciphertext, or std::nullopt on failure.
* @param pubKeySlice The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param blindingFactor The randomness used as blinding factor r
* (size=xrpl::ecBlindingFactorLength).
* @return The ciphertext (size=xrpl::ecGamalEncryptedTotalLength), or std::nullopt on failure.
*/
std::optional<Buffer>
encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindingFactor);
@@ -240,10 +242,11 @@ encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindin
* Creates a deterministic encryption of zero that is unique to the account
* and MPT issuance. Used to initialize confidential balance fields.
*
* @param pubKeySlice The holder's ElGamal public key (64 bytes).
* @param pubKeySlice The holder's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param account The account ID of the token holder.
* @param mptId The MPToken Issuance ID.
* @return The 66-byte canonical zero ciphertext, or std::nullopt on failure.
* @return The canonical zero ciphertext (size=xrpl::ecGamalEncryptedTotalLength), or std::nullopt
* on failure.
*/
std::optional<Buffer>
encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, MPTID const& mptId);
@@ -254,8 +257,8 @@ encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, M
* Proves that the submitter knows the secret key corresponding to the
* provided public key, without revealing the secret key itself.
*
* @param pubKeySlice The ElGamal public key (64 bytes).
* @param proofSlice The Schnorr proof (65 bytes).
* @param pubKeySlice The ElGamal public key (size=xrpl::ecPubKeyLength).
* @param proofSlice The Schnorr proof (size=xrpl::ecSchnorrProofLength).
* @param contextHash The 256-bit context hash binding the proof.
* @return tesSUCCESS if valid, or an error code otherwise.
*/
@@ -269,9 +272,9 @@ verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 co
* ciphertext was correctly constructed using ElGamal encryption.
*
* @param amount The revealed plaintext amount.
* @param blindingFactor The 32-byte blinding factor used in encryption.
* @param pubKeySlice The recipient's ElGamal public key (64 bytes).
* @param ciphertext The ciphertext to verify (66 bytes).
* @param blindingFactor The blinding factor used in encryption (size=xrpl::ecBlindingFactorLength).
* @param pubKeySlice The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param ciphertext The ciphertext to verify (size=xrpl::ecGamalEncryptedTotalLength).
* @return tesSUCCESS if the encryption is valid, or an error code otherwise.
*/
TER
@@ -302,7 +305,8 @@ checkEncryptedAmountFormat(STObject const& object);
* issuer, and optionally the auditor using their respective public keys.
*
* @param amount The revealed plaintext amount.
* @param blindingFactor The 32-byte blinding factor used in all encryptions.
* @param blindingFactor The blinding factor used in all encryptions
* (size=xrpl::ecBlindingFactorLength).
* @param holder The holder's public key and encrypted amount.
* @param issuer The issuer's public key and encrypted amount.
* @param auditor Optional auditor's public key and encrypted amount.
@@ -331,6 +335,22 @@ getConfidentialRecipientCount(bool hasAuditor)
return hasAuditor ? 4 : 3;
}
/**
* @brief Returns the size of a multi-ciphertext equality proof.
*
* Computes the byte size required for a zero-knowledge proof that demonstrates
* multiple ciphertexts encrypt the same plaintext value. The size depends on
* the number of recipients.
*
* @param nRecipients The number of recipients (typically 3 or 4).
* @return The proof size in bytes.
*/
inline std::size_t
getEqualityProofSize(std::size_t nRecipients)
{
return secp256k1_mpt_proof_equality_shared_r_size(nRecipients);
}
/**
* @brief Verifies a multi-ciphertext equality proof.
*
@@ -462,11 +482,10 @@ verifyAggregatedBulletproof(
*
* @param balanceCommitment The compressed Pedersen commitment to the balance (33 bytes).
* @param amountCommitment The compressed Pedersen commitment to the amount (33 bytes).
* @param out Output buffer for the resulting remainder commitment (33 bytes).
* @return tesSUCCESS on success, tecINTERNAL on failure.
* @return The remainder commitment (33 bytes), or std::nullopt on failure.
*/
TER
computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitment, Buffer& out);
std::optional<Buffer>
computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitment);
/**
* @brief Computes the remainder commitment for ConvertBack.
@@ -476,9 +495,8 @@ computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitme
*
* @param commitment The compressed Pedersen commitment (33 bytes).
* @param amount The amount to subtract (must be non-zero).
* @param out Output buffer for the resulting commitment (33 bytes).
* @return tesSUCCESS on success, tecINTERNAL on failure or if amount is 0.
* @return The remainder commitment (33 bytes), or std::nullopt on failure or if amount is 0.
*/
TER
computeConvertBackRemainder(Slice const& commitment, uint64_t amount, Buffer& out);
std::optional<Buffer>
computeConvertBackRemainder(Slice const& commitment, uint64_t amount);
} // namespace xrpl

View File

@@ -206,6 +206,7 @@ TYPED_SFIELD(sfParentBatchID, UINT256, 36)
TYPED_SFIELD(sfLoanBrokerID, UINT256, 37,
SField::sMD_PseudoAccount | SField::sMD_Default)
TYPED_SFIELD(sfLoanID, UINT256, 38)
TYPED_SFIELD(sfBlindingFactor, UINT256, 39)
// number (common)
TYPED_SFIELD(sfNumber, NUMBER, 1)
@@ -312,9 +313,8 @@ TYPED_SFIELD(sfDestinationEncryptedAmount, VL, 41)
TYPED_SFIELD(sfAuditorEncryptedBalance, VL, 42)
TYPED_SFIELD(sfAuditorEncryptedAmount, VL, 43)
TYPED_SFIELD(sfAuditorEncryptionKey, VL, 44)
TYPED_SFIELD(sfBlindingFactor, VL, 45)
TYPED_SFIELD(sfAmountCommitment, VL, 46)
TYPED_SFIELD(sfBalanceCommitment, VL, 47)
TYPED_SFIELD(sfAmountCommitment, VL, 45)
TYPED_SFIELD(sfBalanceCommitment, VL, 46)
// account (common)
TYPED_SFIELD(sfAccount, ACCOUNT, 1)

View File

@@ -32,6 +32,9 @@ namespace xrpl {
*/
class ConfidentialMPTSend : public Transactor
{
/// Size of two Pedersen linkage proofs (amount + balance)
static constexpr std::size_t doublePedersenProofLength = 2 * ecPedersenProofLength;
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};