mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Add doxygen comments for new transactions and helper functions (#6332)
This commit is contained in:
@@ -16,13 +16,29 @@
|
||||
#include <secp256k1.h>
|
||||
|
||||
namespace xrpl {
|
||||
// Helper struct to bundle the ElGamal Public Key and the associated Ciphertext
|
||||
|
||||
/**
|
||||
* @brief Bundles an ElGamal public key with its associated encrypted amount.
|
||||
*
|
||||
* Used to represent a recipient in confidential transfers, containing both
|
||||
* the recipient's ElGamal public key and the ciphertext encrypting the
|
||||
* transfer amount under that key.
|
||||
*/
|
||||
struct ConfidentialRecipient
|
||||
{
|
||||
Slice const publicKey;
|
||||
Slice const encryptedAmount;
|
||||
Slice const publicKey; ///< The recipient's ElGamal public key (64 bytes).
|
||||
Slice const encryptedAmount; ///< The encrypted amount ciphertext (128 bytes).
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Increments the confidential balance version counter on an MPToken.
|
||||
*
|
||||
* The version counter is used to prevent replay attacks by binding proofs
|
||||
* to a specific state of the account's confidential balance. Wraps to 0
|
||||
* on overflow (defined behavior for unsigned integers).
|
||||
*
|
||||
* @param mptoken The MPToken ledger entry to update.
|
||||
*/
|
||||
inline void
|
||||
incrementConfidentialVersion(STObject& mptoken)
|
||||
{
|
||||
@@ -32,6 +48,19 @@ incrementConfidentialVersion(STObject& mptoken)
|
||||
mptoken[sfConfidentialBalanceVersion] = mptoken[~sfConfidentialBalanceVersion].value_or(0u) + 1u;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds common fields to a serializer for ZKP context hash generation.
|
||||
*
|
||||
* Serializes the transaction type, account, sequence number, and issuance ID
|
||||
* into the provided serializer. These fields form the base of all context
|
||||
* hashes used in zero-knowledge proofs.
|
||||
*
|
||||
* @param s The serializer to append fields to.
|
||||
* @param txType The transaction type identifier.
|
||||
* @param account The account ID of the transaction sender.
|
||||
* @param sequence The transaction sequence number.
|
||||
* @param issuanceID The MPToken Issuance ID.
|
||||
*/
|
||||
void
|
||||
addCommonZKPFields(
|
||||
Serializer& s,
|
||||
@@ -40,6 +69,19 @@ addCommonZKPFields(
|
||||
std::uint32_t sequence,
|
||||
uint192 const& issuanceID);
|
||||
|
||||
/**
|
||||
* @brief Generates the context hash for ConfidentialMPTSend transactions.
|
||||
*
|
||||
* Creates a unique 256-bit hash that binds the zero-knowledge proofs to
|
||||
* this specific send transaction, preventing proof reuse across transactions.
|
||||
*
|
||||
* @param account The sender's account ID.
|
||||
* @param sequence The transaction sequence number.
|
||||
* @param issuanceID The MPToken Issuance ID.
|
||||
* @param destination The destination account ID.
|
||||
* @param version The sender's confidential balance version.
|
||||
* @return A 256-bit context hash unique to this transaction.
|
||||
*/
|
||||
uint256
|
||||
getSendContextHash(
|
||||
AccountID const& account,
|
||||
@@ -48,6 +90,19 @@ getSendContextHash(
|
||||
AccountID const& destination,
|
||||
std::uint32_t version);
|
||||
|
||||
/**
|
||||
* @brief Generates the context hash for ConfidentialMPTClawback transactions.
|
||||
*
|
||||
* Creates a unique 256-bit hash that binds the equality proof to this
|
||||
* specific clawback transaction.
|
||||
*
|
||||
* @param account The issuer's account ID.
|
||||
* @param sequence The transaction sequence number.
|
||||
* @param issuanceID The MPToken Issuance ID.
|
||||
* @param amount The amount being clawed back.
|
||||
* @param holder The holder's account ID being clawed back from.
|
||||
* @return A 256-bit context hash unique to this transaction.
|
||||
*/
|
||||
uint256
|
||||
getClawbackContextHash(
|
||||
AccountID const& account,
|
||||
@@ -56,6 +111,18 @@ getClawbackContextHash(
|
||||
std::uint64_t amount,
|
||||
AccountID const& holder);
|
||||
|
||||
/**
|
||||
* @brief Generates the context hash for ConfidentialMPTConvert transactions.
|
||||
*
|
||||
* Creates a unique 256-bit hash that binds the Schnorr proof (for key
|
||||
* registration) to this specific convert transaction.
|
||||
*
|
||||
* @param account The holder's account ID.
|
||||
* @param sequence The transaction sequence number.
|
||||
* @param issuanceID The MPToken Issuance ID.
|
||||
* @param amount The amount being converted to confidential.
|
||||
* @return A 256-bit context hash unique to this transaction.
|
||||
*/
|
||||
uint256
|
||||
getConvertContextHash(
|
||||
AccountID const& account,
|
||||
@@ -63,6 +130,19 @@ getConvertContextHash(
|
||||
uint192 const& issuanceID,
|
||||
std::uint64_t amount);
|
||||
|
||||
/**
|
||||
* @brief Generates the context hash for ConfidentialMPTConvertBack transactions.
|
||||
*
|
||||
* Creates a unique 256-bit hash that binds the zero-knowledge proofs to
|
||||
* this specific convert-back transaction.
|
||||
*
|
||||
* @param account The holder's account ID.
|
||||
* @param sequence The transaction sequence number.
|
||||
* @param issuanceID The MPToken Issuance ID.
|
||||
* @param amount The amount being converted back to public.
|
||||
* @param version The holder's confidential balance version.
|
||||
* @return A 256-bit context hash unique to this transaction.
|
||||
*/
|
||||
uint256
|
||||
getConvertBackContextHash(
|
||||
AccountID const& account,
|
||||
@@ -71,39 +151,125 @@ getConvertBackContextHash(
|
||||
std::uint64_t amount,
|
||||
std::uint32_t version);
|
||||
|
||||
// breaks a 66-byte encrypted amount into two 33-byte components
|
||||
// then parses each 33-byte component into 64-byte secp256k1_pubkey format
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
bool
|
||||
makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2);
|
||||
|
||||
// serialize two secp256k1_pubkey components back into compressed 66-byte form
|
||||
/**
|
||||
* @brief Serializes two secp256k1 public key components into compressed form.
|
||||
*
|
||||
* Converts two secp256k1_pubkey structures (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.
|
||||
*/
|
||||
bool
|
||||
serializeEcPair(secp256k1_pubkey const& in1, secp256k1_pubkey const& in2, Buffer& buffer);
|
||||
|
||||
/**
|
||||
* @brief Verifies that a buffer contains two valid, parsable EC public keys.
|
||||
*
|
||||
* @param buffer The input buffer containing two concatenated components.
|
||||
* @return true if both components can be parsed successfully, false otherwise.
|
||||
*/
|
||||
bool
|
||||
isValidCiphertext(Slice const& buffer);
|
||||
|
||||
/**
|
||||
* @brief Homomorphically adds two ElGamal ciphertexts.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
TER
|
||||
homomorphicAdd(Slice const& a, Slice const& b, Buffer& out);
|
||||
|
||||
/**
|
||||
* @brief Homomorphically subtracts two ElGamal ciphertexts.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
TER
|
||||
homomorphicSubtract(Slice const& a, Slice const& b, Buffer& out);
|
||||
|
||||
// returns ciphertext and the blinding factor used
|
||||
/**
|
||||
* @brief Encrypts an amount using ElGamal encryption.
|
||||
*
|
||||
* Produces a ciphertext C = (C1, C2) where C1 = r*G and C2 = m*G + r*Pk,
|
||||
* 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.
|
||||
*/
|
||||
std::optional<Buffer>
|
||||
encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindingFactor);
|
||||
|
||||
/**
|
||||
* @brief Generates the canonical zero encryption for a specific MPToken.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
std::optional<Buffer>
|
||||
encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, MPTID const& mptId);
|
||||
|
||||
/**
|
||||
* @brief Verifies a Schnorr proof of knowledge of an ElGamal private key.
|
||||
*
|
||||
* 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 contextHash The 256-bit context hash binding the proof.
|
||||
* @return tesSUCCESS if valid, or an error code otherwise.
|
||||
*/
|
||||
TER
|
||||
verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 const& contextHash);
|
||||
|
||||
/**
|
||||
* @brief Verifies that a ciphertext correctly encrypts a revealed amount.
|
||||
*
|
||||
* Given the plaintext amount and blinding factor, verifies that the
|
||||
* 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).
|
||||
* @return tesSUCCESS if the encryption is valid, or an error code otherwise.
|
||||
*/
|
||||
TER
|
||||
verifyElGamalEncryption(
|
||||
std::uint64_t const amount,
|
||||
@@ -111,9 +277,31 @@ verifyElGamalEncryption(
|
||||
Slice const& pubKeySlice,
|
||||
Slice const& ciphertext);
|
||||
|
||||
/**
|
||||
* @brief Validates the format of encrypted amount fields in a transaction.
|
||||
*
|
||||
* Checks that all ciphertext fields in the transaction object have the
|
||||
* correct length and contain valid EC points.
|
||||
*
|
||||
* @param object The transaction object containing encrypted amount fields.
|
||||
* @return tesSUCCESS if all formats are valid, or an error code otherwise.
|
||||
*/
|
||||
NotTEC
|
||||
checkEncryptedAmountFormat(STObject const& object);
|
||||
|
||||
/**
|
||||
* @brief Verifies revealed amount encryptions for all recipients.
|
||||
*
|
||||
* Validates that the same amount was correctly encrypted for the holder,
|
||||
* 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 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.
|
||||
* @return tesSUCCESS if all encryptions are valid, or an error code otherwise.
|
||||
*/
|
||||
TER
|
||||
verifyRevealedAmount(
|
||||
std::uint64_t const amount,
|
||||
@@ -122,15 +310,45 @@ verifyRevealedAmount(
|
||||
ConfidentialRecipient const& issuer,
|
||||
std::optional<ConfidentialRecipient> const& auditor);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of recipients in a confidential transfer.
|
||||
*
|
||||
* Returns 4 if an auditor is present (sender, destination, issuer, auditor),
|
||||
* or 3 if no auditor (sender, destination, issuer).
|
||||
*
|
||||
* @param hasAuditor Whether the issuance has an auditor configured.
|
||||
* @return The number of recipients (3 or 4).
|
||||
*/
|
||||
constexpr std::size_t
|
||||
getConfidentialRecipientCount(bool hasAuditor)
|
||||
{
|
||||
return hasAuditor ? 4 : 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the size of a multi-ciphertext equality proof.
|
||||
*
|
||||
* The proof size varies based on the number of recipients because each
|
||||
* additional recipient requires additional proof components.
|
||||
*
|
||||
* @param nRecipients The number of recipients in the transfer.
|
||||
* @return The size in bytes of the equality proof.
|
||||
*/
|
||||
std::size_t
|
||||
getMultiCiphertextEqualityProofSize(std::size_t nRecipients);
|
||||
|
||||
/**
|
||||
* @brief Verifies a multi-ciphertext equality proof.
|
||||
*
|
||||
* Proves that all ciphertexts in the recipients vector encrypt the same
|
||||
* plaintext amount, without revealing the amount itself.
|
||||
*
|
||||
* @param proof The zero-knowledge proof bytes.
|
||||
* @param recipients Vector of recipients with their public keys and ciphertexts.
|
||||
* @param nRecipients The number of recipients (must match recipients.size()).
|
||||
* @param contextHash The 256-bit context hash binding the proof.
|
||||
* @return tesSUCCESS if the proof is valid, or an error code otherwise.
|
||||
*/
|
||||
TER
|
||||
verifyMultiCiphertextEqualityProof(
|
||||
Slice const& proof,
|
||||
@@ -138,6 +356,20 @@ verifyMultiCiphertextEqualityProof(
|
||||
std::size_t const nRecipients,
|
||||
uint256 const& contextHash);
|
||||
|
||||
/**
|
||||
* @brief Verifies a clawback equality proof.
|
||||
*
|
||||
* Proves that the issuer knows the exact amount encrypted in the holder's
|
||||
* balance ciphertext. Used in ConfidentialMPTClawback to verify the issuer
|
||||
* can decrypt the balance using their private key.
|
||||
*
|
||||
* @param amount The revealed plaintext amount.
|
||||
* @param proof The zero-knowledge proof bytes.
|
||||
* @param pubKeySlice The issuer's ElGamal public key (64 bytes).
|
||||
* @param ciphertext The issuer's encrypted balance on the holder's account (66 bytes).
|
||||
* @param contextHash The 256-bit context hash binding the proof.
|
||||
* @return tesSUCCESS if the proof is valid, or an error code otherwise.
|
||||
*/
|
||||
TER
|
||||
verifyClawbackEqualityProof(
|
||||
uint64_t const amount,
|
||||
@@ -146,7 +378,14 @@ verifyClawbackEqualityProof(
|
||||
Slice const& ciphertext,
|
||||
uint256 const& contextHash);
|
||||
|
||||
// generates a 32 byte randomness factor to be used in encryption and proofs
|
||||
/**
|
||||
* @brief Generates a cryptographically secure 32-byte blinding factor.
|
||||
*
|
||||
* Produces random bytes suitable for use as an ElGamal blinding factor
|
||||
* or Pedersen commitment randomness.
|
||||
*
|
||||
* @return A 32-byte buffer containing the random blinding factor.
|
||||
*/
|
||||
Buffer
|
||||
generateBlindingFactor();
|
||||
|
||||
|
||||
@@ -117,12 +117,8 @@ serializeEcPair(secp256k1_pubkey const& in1, secp256k1_pubkey const& in2, Buffer
|
||||
bool
|
||||
isValidCiphertext(Slice const& buffer)
|
||||
{
|
||||
// Local/temporary variables to pass to makeEcPair.
|
||||
// Their contents will be discarded when the function returns.
|
||||
secp256k1_pubkey key1;
|
||||
secp256k1_pubkey key2;
|
||||
|
||||
// Call makeEcPair and return its result.
|
||||
return makeEcPair(buffer, key1, key2);
|
||||
}
|
||||
|
||||
@@ -193,22 +189,16 @@ generateBlindingFactor()
|
||||
std::optional<Buffer>
|
||||
encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindingFactor)
|
||||
{
|
||||
Buffer buf(ecGamalEncryptedTotalLength);
|
||||
|
||||
// Allocate ciphertext placeholders
|
||||
secp256k1_pubkey c1, c2;
|
||||
secp256k1_pubkey pubKey;
|
||||
|
||||
if (blindingFactor.size() != ecBlindingFactorLength)
|
||||
return std::nullopt;
|
||||
|
||||
secp256k1_pubkey c1, c2, pubKey;
|
||||
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
|
||||
|
||||
// Encrypt the amount
|
||||
if (!secp256k1_elgamal_encrypt(secp256k1Context(), &c1, &c2, &pubKey, amt, blindingFactor.data()))
|
||||
return std::nullopt;
|
||||
|
||||
// Serialize the ciphertext pair into the buffer
|
||||
Buffer buf(ecGamalEncryptedTotalLength);
|
||||
if (!serializeEcPair(c1, c2, buf))
|
||||
return std::nullopt;
|
||||
|
||||
@@ -221,18 +211,13 @@ encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, M
|
||||
if (pubKeySlice.size() != ecPubKeyLength)
|
||||
return std::nullopt; // LCOV_EXCL_LINE
|
||||
|
||||
secp256k1_pubkey c1, c2;
|
||||
secp256k1_pubkey pubKey;
|
||||
|
||||
secp256k1_pubkey c1, c2, pubKey;
|
||||
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
|
||||
|
||||
// Encrypt the amount
|
||||
if (!generate_canonical_encrypted_zero(secp256k1Context(), &c1, &c2, &pubKey, account.data(), mptId.data()))
|
||||
return std::nullopt;
|
||||
|
||||
Buffer buf(ecGamalEncryptedTotalLength);
|
||||
|
||||
// Serialize the ciphertext pair into the buffer
|
||||
if (!serializeEcPair(c1, c2, buf))
|
||||
return std::nullopt;
|
||||
|
||||
@@ -242,20 +227,16 @@ encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, M
|
||||
TER
|
||||
verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 const& contextHash)
|
||||
{
|
||||
// sanity check proof length
|
||||
if (proofSlice.size() != ecSchnorrProofLength)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
// sanity check public key length
|
||||
if (pubKeySlice.size() != ecPubKeyLength)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
secp256k1_pubkey pubKey;
|
||||
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
|
||||
|
||||
int result = secp256k1_mpt_pok_sk_verify(secp256k1Context(), proofSlice.data(), &pubKey, contextHash.data());
|
||||
|
||||
if (result != 1)
|
||||
if (secp256k1_mpt_pok_sk_verify(secp256k1Context(), proofSlice.data(), &pubKey, contextHash.data()) != 1)
|
||||
return tecBAD_PROOF;
|
||||
|
||||
return tesSUCCESS;
|
||||
@@ -268,11 +249,9 @@ verifyElGamalEncryption(
|
||||
Slice const& pubKeySlice,
|
||||
Slice const& ciphertext)
|
||||
{
|
||||
// sanity check blinding factor length
|
||||
if (blindingFactor.size() != ecBlindingFactorLength)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
// sanity check public key length
|
||||
if (pubKeySlice.size() != ecPubKeyLength)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
@@ -283,13 +262,8 @@ verifyElGamalEncryption(
|
||||
if (!makeEcPair(ciphertext, c1, c2))
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
int result =
|
||||
secp256k1_elgamal_verify_encryption(secp256k1Context(), &c1, &c2, &pubKey, amount, blindingFactor.data());
|
||||
|
||||
if (result != 1)
|
||||
{
|
||||
if (secp256k1_elgamal_verify_encryption(secp256k1Context(), &c1, &c2, &pubKey, amount, blindingFactor.data()) != 1)
|
||||
return tecBAD_PROOF;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
@@ -392,6 +366,9 @@ verifyClawbackEqualityProof(
|
||||
secp256k1_pubkey pubKey;
|
||||
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -484,6 +461,8 @@ verifyBalancePcmLinkage(
|
||||
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
|
||||
std::memcpy(pcm.data, pcmSlice.data(), ecPubKeyLength);
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -517,7 +496,6 @@ secp256k1_elgamal_generate_keypair(secp256k1_context const* ctx, unsigned char*
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
// ... implementation of secp256k1_elgamal_encrypt ...
|
||||
int
|
||||
secp256k1_elgamal_encrypt(
|
||||
secp256k1_context const* ctx,
|
||||
@@ -579,7 +557,6 @@ secp256k1_elgamal_encrypt(
|
||||
return 1; // Success
|
||||
}
|
||||
|
||||
// ... implementation of secp256k1_elgamal_decrypt ...
|
||||
int
|
||||
secp256k1_elgamal_decrypt(
|
||||
secp256k1_context const* ctx,
|
||||
|
||||
@@ -5,6 +5,22 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Allows an MPT issuer to clawback confidential balances from a holder.
|
||||
*
|
||||
* This transaction enables the issuer of an MPToken Issuance (with clawback
|
||||
* enabled) to reclaim confidential tokens from a holder's account. Unlike
|
||||
* regular clawback, the issuer cannot see the holder's balance directly.
|
||||
* Instead, the issuer must provide a zero-knowledge proof that demonstrates
|
||||
* they know the exact encrypted balance amount.
|
||||
*
|
||||
* @par Cryptographic Operations:
|
||||
* - **Equality Proof Verification**: Verifies that the issuer's revealed
|
||||
* amount matches the holder's encrypted balance using the issuer's
|
||||
* ElGamal private key.
|
||||
*
|
||||
* @see ConfidentialMPTSend, ConfidentialMPTConvert
|
||||
*/
|
||||
class ConfidentialMPTClawback : public Transactor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,24 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Converts public (plaintext) MPT balance to confidential (encrypted)
|
||||
* balance.
|
||||
*
|
||||
* This transaction allows a token holder to convert their publicly visible
|
||||
* MPToken balance into an encrypted confidential balance. Once converted,
|
||||
* the balance can only be spent using ConfidentialMPTSend transactions and
|
||||
* remains hidden from public view on the ledger.
|
||||
*
|
||||
* @par Cryptographic Operations:
|
||||
* - **Schnorr Proof Verification**: When registering a new ElGamal public key,
|
||||
* verifies proof of knowledge of the corresponding private key.
|
||||
* - **Revealed Amount Verification**: Verifies that the provided encrypted
|
||||
* amounts (for holder, issuer, and optionally auditor) all encrypt the
|
||||
* same plaintext amount using the provided blinding factor.
|
||||
*
|
||||
* @see ConfidentialMPTConvertBack, ConfidentialMPTSend
|
||||
*/
|
||||
class ConfidentialMPTConvert : public Transactor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,25 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Converts confidential (encrypted) MPT balance back to public
|
||||
* (plaintext) balance.
|
||||
*
|
||||
* This transaction allows a token holder to convert their encrypted
|
||||
* confidential balance back into a publicly visible MPToken balance. The
|
||||
* holder must prove they have sufficient confidential balance without
|
||||
* revealing the actual balance amount.
|
||||
*
|
||||
* @par Cryptographic Operations:
|
||||
* - **Revealed Amount Verification**: Verifies that the provided encrypted
|
||||
* amounts correctly encrypt the conversion amount.
|
||||
* - **Pedersen Linkage Proof**: Verifies that the provided balance commitment
|
||||
* correctly links to the holder's encrypted spending balance.
|
||||
* - **Bulletproof Range Proof**: Verifies that the remaining balance (after
|
||||
* conversion) is non-negative, ensuring the holder has sufficient funds.
|
||||
*
|
||||
* @see ConfidentialMPTConvert, ConfidentialMPTSend
|
||||
*/
|
||||
class ConfidentialMPTConvertBack : public Transactor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,26 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Merges the confidential inbox balance into the spending balance.
|
||||
*
|
||||
* In the confidential transfer system, incoming funds are deposited into an
|
||||
* "inbox" balance that the recipient cannot immediately spend. This prevents
|
||||
* front-running attacks where an attacker could invalidate a pending
|
||||
* transaction by sending funds to the sender. This transaction merges the
|
||||
* inbox into the spending balance, making those funds available for spending.
|
||||
*
|
||||
* @par Cryptographic Operations:
|
||||
* - **Homomorphic Addition**: Adds the encrypted inbox balance to the
|
||||
* encrypted spending balance using ElGamal homomorphic properties.
|
||||
* - **Zero Encryption**: Resets the inbox to an encryption of zero.
|
||||
*
|
||||
* @note This transaction requires no zero-knowledge proofs because it only
|
||||
* combines encrypted values that the holder already owns. The
|
||||
* homomorphic properties of ElGamal encryption ensure correctness.
|
||||
*
|
||||
* @see ConfidentialMPTSend, ConfidentialMPTConvert
|
||||
*/
|
||||
class ConfidentialMPTMergeInbox : public Transactor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,32 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Transfers confidential MPT tokens between holders privately.
|
||||
*
|
||||
* This transaction enables private token transfers where the transfer amount
|
||||
* is hidden from public view. Both sender and recipient must have initialized
|
||||
* confidential balances. The transaction provides encrypted amounts for all
|
||||
* parties (sender, destination, issuer, and optionally auditor) along with
|
||||
* zero-knowledge proofs that verify correctness without revealing the amount.
|
||||
*
|
||||
* @par Cryptographic Operations:
|
||||
* - **Multi-Ciphertext Equality Proof**: Verifies that all encrypted amounts
|
||||
* (sender, destination, issuer, auditor) encrypt the same plaintext value.
|
||||
* - **Amount Pedersen Linkage Proof**: Verifies that the amount commitment
|
||||
* correctly links to the sender's encrypted amount.
|
||||
* - **Balance Pedersen Linkage Proof**: Verifies that the balance commitment
|
||||
* correctly links to the sender's encrypted spending balance.
|
||||
* - **Bulletproof Range Proof**: Verifies remaining balance and
|
||||
* transfer amount are non-negative.
|
||||
*
|
||||
* @note Funds are deposited into the destination's inbox, not spending
|
||||
* balance. The recipient must call ConfidentialMPTMergeInbox to make
|
||||
* received funds spendable.
|
||||
*
|
||||
* @see ConfidentialMPTMergeInbox, ConfidentialMPTConvert,
|
||||
* ConfidentialMPTConvertBack
|
||||
*/
|
||||
class ConfidentialMPTSend : public Transactor
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user