chore: Apply clang-format width 100 (#6516)

This commit is contained in:
Shawn Xie
2026-03-10 11:24:01 -04:00
committed by GitHub
parent 36c1c5f3cd
commit 84cc8599af
17 changed files with 797 additions and 352 deletions

View File

@@ -44,7 +44,8 @@ incrementConfidentialVersion(STObject& mptoken)
// Retrieve current version and increment.
// Unsigned integer overflow is defined behavior in C++ (wraps to 0),
// which is acceptable here.
mptoken[sfConfidentialBalanceVersion] = mptoken[~sfConfidentialBalanceVersion].value_or(0u) + 1u;
mptoken[sfConfidentialBalanceVersion] =
mptoken[~sfConfidentialBalanceVersion].value_or(0u) + 1u;
}
/**

View File

@@ -40,4 +40,3 @@ public:
};
} // namespace xrpl

View File

@@ -42,4 +42,3 @@ public:
};
} // namespace xrpl

View File

@@ -43,4 +43,3 @@ public:
};
} // namespace xrpl

View File

@@ -44,4 +44,3 @@ public:
};
} // namespace xrpl

View File

@@ -50,4 +50,3 @@ public:
};
} // namespace xrpl

View File

@@ -524,7 +524,8 @@ accountHolds(
// Only if auth check is needed, as it needs to do an additional read
// operation. Note featureSingleAssetVault will affect error codes.
if (zeroIfUnauthorized == ahZERO_IF_UNAUTHORIZED &&
(view.rules().enabled(featureSingleAssetVault) || view.rules().enabled(featureConfidentialTransfer)))
(view.rules().enabled(featureSingleAssetVault) ||
view.rules().enabled(featureConfidentialTransfer)))
{
if (auto const err = requireAuth(view, mptIssue, account, AuthType::StrongAuth);
!isTesSuccess(err))

View File

@@ -95,7 +95,10 @@ makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2)
auto parsePubKey = [](Slice const& slice, secp256k1_pubkey& out) {
return secp256k1_ec_pubkey_parse(
secp256k1Context(), &out, reinterpret_cast<unsigned char const*>(slice.data()), slice.length());
secp256k1Context(),
&out,
reinterpret_cast<unsigned char const*>(slice.data()),
slice.length());
};
Slice s1{buffer.data(), ecGamalEncryptedLength};
@@ -112,7 +115,8 @@ serializeEcPair(secp256k1_pubkey const& in1, secp256k1_pubkey const& in2, Buffer
{
auto serializePubKey = [](secp256k1_pubkey const& pub, unsigned char* out) {
size_t outLen = ecGamalEncryptedLength; // 33 bytes
int const ret = secp256k1_ec_pubkey_serialize(secp256k1Context(), out, &outLen, &pub, SECP256K1_EC_COMPRESSED);
int const ret = secp256k1_ec_pubkey_serialize(
secp256k1Context(), out, &outLen, &pub, SECP256K1_EC_COMPRESSED);
return ret == 1 && outLen == ecGamalEncryptedLength;
};
@@ -188,7 +192,8 @@ homomorphicSubtract(Slice const& a, Slice const& b, Buffer& out)
secp256k1_pubkey diffC1;
secp256k1_pubkey diffC2;
if (secp256k1_elgamal_subtract(secp256k1Context(), &diffC1, &diffC2, &aC1, &aC2, &bC1, &bC2) != 1)
if (secp256k1_elgamal_subtract(secp256k1Context(), &diffC1, &diffC2, &aC1, &aC2, &bC1, &bC2) !=
1)
return tecINTERNAL;
if (!serializeEcPair(diffC1, diffC2, out))
@@ -219,10 +224,12 @@ encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindin
return std::nullopt;
secp256k1_pubkey c1, c2, pubKey;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
return std::nullopt;
if (!secp256k1_elgamal_encrypt(secp256k1Context(), &c1, &c2, &pubKey, amt, blindingFactor.data()))
if (!secp256k1_elgamal_encrypt(
secp256k1Context(), &c1, &c2, &pubKey, amt, blindingFactor.data()))
return std::nullopt;
Buffer buf(ecGamalEncryptedTotalLength);
@@ -239,10 +246,12 @@ encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, M
return std::nullopt; // LCOV_EXCL_LINE
secp256k1_pubkey c1, c2, pubKey;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
return std::nullopt; // LCOV_EXCL_LINE
if (!generate_canonical_encrypted_zero(secp256k1Context(), &c1, &c2, &pubKey, account.data(), mptId.data()))
if (!generate_canonical_encrypted_zero(
secp256k1Context(), &c1, &c2, &pubKey, account.data(), mptId.data()))
return std::nullopt; // LCOV_EXCL_LINE
Buffer buf(ecGamalEncryptedTotalLength);
@@ -262,10 +271,12 @@ 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 (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
if (secp256k1_mpt_pok_sk_verify(secp256k1Context(), proofSlice.data(), &pubKey, contextHash.data()) != 1)
if (secp256k1_mpt_pok_sk_verify(
secp256k1Context(), proofSlice.data(), &pubKey, contextHash.data()) != 1)
return tecBAD_PROOF;
return tesSUCCESS;
@@ -278,19 +289,21 @@ verifyElGamalEncryption(
Slice const& pubKeySlice,
Slice const& ciphertext)
{
if (ciphertext.size() != ecGamalEncryptedTotalLength || blindingFactor.size() != ecBlindingFactorLength ||
pubKeySlice.size() != ecPubKeyLength)
if (ciphertext.size() != ecGamalEncryptedTotalLength ||
blindingFactor.size() != ecBlindingFactorLength || pubKeySlice.size() != ecPubKeyLength)
return tecINTERNAL; // LCOV_EXCL_LINE
secp256k1_pubkey pubKey;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
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 (secp256k1_elgamal_verify_encryption(
secp256k1Context(), &c1, &c2, &pubKey, amount, blindingFactor.data()) != 1)
return tecBAD_PROOF;
return tesSUCCESS;
@@ -304,13 +317,15 @@ verifyRevealedAmount(
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor)
{
if (auto const res = verifyElGamalEncryption(amount, blindingFactor, holder.publicKey, holder.encryptedAmount);
if (auto const res = verifyElGamalEncryption(
amount, blindingFactor, holder.publicKey, holder.encryptedAmount);
!isTesSuccess(res))
{
return res;
}
if (auto const res = verifyElGamalEncryption(amount, blindingFactor, issuer.publicKey, issuer.encryptedAmount);
if (auto const res = verifyElGamalEncryption(
amount, blindingFactor, issuer.publicKey, issuer.encryptedAmount);
!isTesSuccess(res))
{
return res;
@@ -318,8 +333,8 @@ verifyRevealedAmount(
if (auditor)
{
if (auto const res =
verifyElGamalEncryption(amount, blindingFactor, auditor->publicKey, auditor->encryptedAmount);
if (auto const res = verifyElGamalEncryption(
amount, blindingFactor, auditor->publicKey, auditor->encryptedAmount);
!isTesSuccess(res))
{
return res;
@@ -361,28 +376,33 @@ verifyMultiCiphertextEqualityProof(
// Parse Shared C1 from the first recipient only
if (i == 0)
{
if (!secp256k1_ec_pubkey_parse(ctx, &c1, recipient.encryptedAmount.data(), ecGamalEncryptedLength))
if (!secp256k1_ec_pubkey_parse(
ctx, &c1, recipient.encryptedAmount.data(), ecGamalEncryptedLength))
return tecINTERNAL; // LCOV_EXCL_LINE
}
else
{
// All C1 bytes must be the same
if (std::memcmp(
recipient.encryptedAmount.data(), recipients[0].encryptedAmount.data(), ecGamalEncryptedLength) !=
0)
recipient.encryptedAmount.data(),
recipients[0].encryptedAmount.data(),
ecGamalEncryptedLength) != 0)
{
return tecBAD_PROOF;
}
}
if (secp256k1_ec_pubkey_parse(
ctx, &c2_vec[i], recipient.encryptedAmount.data() + ecGamalEncryptedLength, ecGamalEncryptedLength) !=
1)
ctx,
&c2_vec[i],
recipient.encryptedAmount.data() + ecGamalEncryptedLength,
ecGamalEncryptedLength) != 1)
{
return tecINTERNAL; // LCOV_EXCL_LINE
}
if (secp256k1_ec_pubkey_parse(ctx, &pk_vec[i], recipient.publicKey.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
ctx, &pk_vec[i], recipient.publicKey.data(), ecPubKeyLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
}
@@ -412,7 +432,8 @@ verifyClawbackEqualityProof(
return tecINTERNAL; // LCOV_EXCL_LINE
secp256k1_pubkey pubKey;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
// Note: c2, c1 order - the proof is generated with c2 first (the encrypted
@@ -433,7 +454,8 @@ checkEncryptedAmountFormat(STObject const& object)
// Current usage of this function is only for ConfidentialMPTConvert and
// ConfidentialMPTConvertBack transactions, which already enforce that these fields
// are present.
if (!object.isFieldPresent(sfHolderEncryptedAmount) || !object.isFieldPresent(sfIssuerEncryptedAmount))
if (!object.isFieldPresent(sfHolderEncryptedAmount) ||
!object.isFieldPresent(sfIssuerEncryptedAmount))
return temMALFORMED; // LCOV_EXCL_LINE
if (object[sfHolderEncryptedAmount].length() != ecGamalEncryptedTotalLength ||
@@ -444,7 +466,8 @@ checkEncryptedAmountFormat(STObject const& object)
if (hasAuditor && object[sfAuditorEncryptedAmount].length() != ecGamalEncryptedTotalLength)
return temBAD_CIPHERTEXT;
if (!isValidCiphertext(object[sfHolderEncryptedAmount]) || !isValidCiphertext(object[sfIssuerEncryptedAmount]))
if (!isValidCiphertext(object[sfHolderEncryptedAmount]) ||
!isValidCiphertext(object[sfIssuerEncryptedAmount]))
return temBAD_CIPHERTEXT;
if (hasAuditor && !isValidCiphertext(object[sfAuditorEncryptedAmount]))
@@ -475,11 +498,13 @@ verifyAmountPcmLinkage(
return tecINTERNAL; // LCOV_EXCL_LINE
secp256k1_pubkey pubKey;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
secp256k1_pubkey pcm;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
if (secp256k1_elgamal_pedersen_link_verify(
@@ -515,11 +540,13 @@ verifyBalancePcmLinkage(
return tecINTERNAL; // LCOV_EXCL_LINE
secp256k1_pubkey pubKey;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
secp256k1_pubkey pcm;
if (secp256k1_ec_pubkey_parse(secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength) != 1)
if (secp256k1_ec_pubkey_parse(
secp256k1Context(), &pcm, pcmSlice.data(), ecPedersenCommitmentLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
// Note: c2, c1 order - the linkage proof expects the message-containing
@@ -545,7 +572,8 @@ verifyAggregatedBulletproof(
if (m != 1 && m != 2)
return tecINTERNAL; // LCOV_EXCL_LINE
std::size_t const expectedProofLen = (m == 1) ? ecSingleBulletproofLength : ecDoubleBulletproofLength;
std::size_t const expectedProofLen =
(m == 1) ? ecSingleBulletproofLength : ecDoubleBulletproofLength;
if (proof.size() != expectedProofLen)
return tecINTERNAL; // LCOV_EXCL_LINE
@@ -559,7 +587,10 @@ verifyAggregatedBulletproof(
return tecINTERNAL; // LCOV_EXCL_LINE
if (secp256k1_ec_pubkey_parse(
ctx, &commitments[i], compressedCommitments[i].data(), ecPedersenCommitmentLength) != 1)
ctx,
&commitments[i],
compressedCommitments[i].data(),
ecPedersenCommitmentLength) != 1)
return tecINTERNAL; // LCOV_EXCL_LINE
}
@@ -608,17 +639,20 @@ verifyAggregatedBulletproof(
TER
computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitment, Buffer& out)
{
if (balanceCommitment.size() != ecPedersenCommitmentLength || amountCommitment.size() != ecPedersenCommitmentLength)
if (balanceCommitment.size() != ecPedersenCommitmentLength ||
amountCommitment.size() != ecPedersenCommitmentLength)
return tecINTERNAL;
auto const ctx = secp256k1Context();
secp256k1_pubkey pcBalance;
if (secp256k1_ec_pubkey_parse(ctx, &pcBalance, balanceCommitment.data(), ecPedersenCommitmentLength) != 1)
if (secp256k1_ec_pubkey_parse(
ctx, &pcBalance, balanceCommitment.data(), ecPedersenCommitmentLength) != 1)
return tecINTERNAL;
secp256k1_pubkey pcAmount;
if (secp256k1_ec_pubkey_parse(ctx, &pcAmount, amountCommitment.data(), ecPedersenCommitmentLength) != 1)
if (secp256k1_ec_pubkey_parse(
ctx, &pcAmount, amountCommitment.data(), ecPedersenCommitmentLength) != 1)
return tecINTERNAL;
// Negate PC_amount point to get -PC_amount
@@ -634,7 +668,8 @@ computeSendRemainder(Slice const& balanceCommitment, Slice const& amountCommitme
// 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 (secp256k1_ec_pubkey_serialize(ctx, out.data(), &outLen, &pcRem, SECP256K1_EC_COMPRESSED) !=
1)
return tecINTERNAL;
return tesSUCCESS;
@@ -650,7 +685,8 @@ 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 (secp256k1_ec_pubkey_parse(ctx, &pcBalance, commitment.data(), ecPedersenCommitmentLength) !=
1)
return tecINTERNAL; // LCOV_EXCL_LINE
// Convert amount to 32-byte big-endian scalar
@@ -676,7 +712,8 @@ computeConvertBackRemainder(Slice const& commitment, std::uint64_t amount, Buffe
// 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 (secp256k1_ec_pubkey_serialize(ctx, out.data(), &outLen, &pcRem, SECP256K1_EC_COMPRESSED) !=
1 ||
outLen != ecPedersenCommitmentLength)
return tecINTERNAL; // LCOV_EXCL_LINE

View File

@@ -137,8 +137,9 @@ ConfidentialMPTConvert::preclaim(PreclaimContext const& ctx)
std::optional<ConfidentialRecipient> auditor;
if (hasAuditor)
{
auditor.emplace(ConfidentialRecipient{
(*sleIssuance)[sfAuditorElGamalPublicKey], ctx.tx[sfAuditorEncryptedAmount]});
auditor.emplace(
ConfidentialRecipient{
(*sleIssuance)[sfAuditorElGamalPublicKey], ctx.tx[sfAuditorEncryptedAmount]});
}
return verifyRevealedAmount(

View File

@@ -81,8 +81,9 @@ verifyProofs(
bool const hasAuditor = issuance->isFieldPresent(sfAuditorElGamalPublicKey);
if (hasAuditor)
{
auditor.emplace(ConfidentialRecipient{
(*issuance)[sfAuditorElGamalPublicKey], tx[sfAuditorEncryptedAmount]});
auditor.emplace(
ConfidentialRecipient{
(*issuance)[sfAuditorElGamalPublicKey], tx[sfAuditorEncryptedAmount]});
}
// Run all verifications before returning any error to prevent timing attacks

View File

@@ -74,11 +74,13 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
if (ctx.view.rules().enabled(featureConfidentialTransfer))
{
auto const sleMptIssuance = ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
auto const sleMptIssuance =
ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID]));
// if there still existing encrypted balances of MPT in
// circulation
if (sleMptIssuance && (*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0) != 0)
if (sleMptIssuance &&
(*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0) != 0)
{
// this MPT still has encrypted balance, since we don't know
// if it's non-zero or not, we won't allow deletion of

View File

@@ -21,7 +21,8 @@ MPTokenIssuanceCreate::checkExtraFeatures(PreflightContext const& ctx)
// can not set tmfMPTCannotMutatePrivacy without featureConfidentialTransfer
auto const mutableFlags = ctx.tx[~sfMutableFlags];
if (mutableFlags && (*mutableFlags & tmfMPTCannotMutatePrivacy) && !ctx.rules.enabled(featureConfidentialTransfer))
if (mutableFlags && (*mutableFlags & tmfMPTCannotMutatePrivacy) &&
!ctx.rules.enabled(featureConfidentialTransfer))
return false;
return true;

View File

@@ -1,9 +1,9 @@
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/delegate/DelegateUtils.h>
#include <xrpl/tx/transactors/token/MPTokenIssuanceSet.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
namespace xrpl {
@@ -53,7 +53,8 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx)
auto const hasAuditorElGamalKey = ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey);
auto const txFlags = ctx.tx.getFlags();
auto const mutatePrivacy = mutableFlags && ((*mutableFlags & (tmfMPTSetPrivacy | tmfMPTClearPrivacy)));
auto const mutatePrivacy =
mutableFlags && ((*mutableFlags & (tmfMPTSetPrivacy | tmfMPTClearPrivacy)));
auto const hasDomain = ctx.tx.isFieldPresent(sfDomainID);
auto const hasHolder = ctx.tx.isFieldPresent(sfHolder);
@@ -84,7 +85,8 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx)
ctx.rules.enabled(featureConfidentialTransfer))
{
// Is this transaction actually changing anything ?
if (txFlags == 0 && !hasDomain && !hasIssuerElGamalKey && !hasAuditorElGamalKey && !isMutate)
if (txFlags == 0 && !hasDomain && !hasIssuerElGamalKey && !hasAuditorElGamalKey &&
!isMutate)
return temMALFORMED;
}
@@ -233,16 +235,19 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx)
if (mutableFlags)
{
if (std::any_of(
mptMutabilityFlags.begin(), mptMutabilityFlags.end(), [mutableFlags, &isMutableFlag](auto const& f) {
bool const canMutate =
f.isCannotMutate ? isMutableFlag(f.mutabilityFlag) : !isMutableFlag(f.mutabilityFlag);
mptMutabilityFlags.begin(),
mptMutabilityFlags.end(),
[mutableFlags, &isMutableFlag](auto const& f) {
bool const canMutate = f.isCannotMutate ? isMutableFlag(f.mutabilityFlag)
: !isMutableFlag(f.mutabilityFlag);
return canMutate && (*mutableFlags & (f.setFlag | f.clearFlag));
}))
return tecNO_PERMISSION;
if ((*mutableFlags & tmfMPTSetPrivacy) || (*mutableFlags & tmfMPTClearPrivacy))
{
std::uint64_t const confidentialOA = (*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0);
std::uint64_t const confidentialOA =
(*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0);
// If there's any confidential outstanding amount, disallow toggling
// the lsfMPTCanPrivacy flag
@@ -268,29 +273,34 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx)
}
// cannot update issuer public key
if (ctx.tx.isFieldPresent(sfIssuerElGamalPublicKey) && sleMptIssuance->isFieldPresent(sfIssuerElGamalPublicKey))
if (ctx.tx.isFieldPresent(sfIssuerElGamalPublicKey) &&
sleMptIssuance->isFieldPresent(sfIssuerElGamalPublicKey))
{
return tecNO_PERMISSION;
}
// cannot update auditor public key
if (ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey) && sleMptIssuance->isFieldPresent(sfAuditorElGamalPublicKey))
if (ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey) &&
sleMptIssuance->isFieldPresent(sfAuditorElGamalPublicKey))
{
return tecNO_PERMISSION; // LCOV_EXCL_LINE
}
if (ctx.tx.isFieldPresent(sfIssuerElGamalPublicKey) && !sleMptIssuance->isFlag(lsfMPTCanPrivacy))
if (ctx.tx.isFieldPresent(sfIssuerElGamalPublicKey) &&
!sleMptIssuance->isFlag(lsfMPTCanPrivacy))
{
return tecNO_PERMISSION;
}
if (ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey) && !sleMptIssuance->isFlag(lsfMPTCanPrivacy))
if (ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey) &&
!sleMptIssuance->isFlag(lsfMPTCanPrivacy))
{
return tecNO_PERMISSION;
}
// cannot upload key if there's circulating supply of COA
if ((ctx.tx.isFieldPresent(sfIssuerElGamalPublicKey) || ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey)) &&
if ((ctx.tx.isFieldPresent(sfIssuerElGamalPublicKey) ||
ctx.tx.isFieldPresent(sfAuditorElGamalPublicKey)) &&
sleMptIssuance->isFieldPresent(sfConfidentialOutstandingAmount))
{
return tecNO_PERMISSION; // LCOV_EXCL_LINE
@@ -386,7 +396,9 @@ MPTokenIssuanceSet::doApply()
if (auto const pubKey = ctx_.tx[~sfIssuerElGamalPublicKey])
{
// This is enforced in preflight.
XRPL_ASSERT(sle->getType() == ltMPTOKEN_ISSUANCE, "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
XRPL_ASSERT(
sle->getType() == ltMPTOKEN_ISSUANCE,
"MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
sle->setFieldVL(sfIssuerElGamalPublicKey, *pubKey);
}
@@ -394,7 +406,9 @@ MPTokenIssuanceSet::doApply()
if (auto const pubKey = ctx_.tx[~sfAuditorElGamalPublicKey])
{
// This is enforced in preflight.
XRPL_ASSERT(sle->getType() == ltMPTOKEN_ISSUANCE, "MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
XRPL_ASSERT(
sle->getType() == ltMPTOKEN_ISSUANCE,
"MPTokenIssuanceSet::doApply : modifying MPTokenIssuance");
sle->setFieldVL(sfAuditorElGamalPublicKey, *pubKey);
}

File diff suppressed because it is too large Load Diff

View File

@@ -3804,7 +3804,8 @@ class Invariants_test : public beast::unit_test::suite
// Generate an MPT with privacy, issue 100 tokens to A2.
// Perform a confidential conversion to populate encrypted state.
auto const precloseConfidential = [&mptID](Account const& A1, Account const& A2, Env& env) -> bool {
auto const precloseConfidential =
[&mptID](Account const& A1, Account const& A2, Env& env) -> bool {
MPTTester mpt(env, A1, {.holders = {A2}, .fund = false});
mpt.create({.flags = tfMPTCanTransfer | tfMPTCanPrivacy});
mptID = mpt.issuanceID();
@@ -3858,7 +3859,8 @@ class Invariants_test : public beast::unit_test::suite
precloseConfidential);
// requiresPrivacyFlag
auto const precloseNoPrivacy = [&mptID](Account const& A1, Account const& A2, Env& env) -> bool {
auto const precloseNoPrivacy = [&mptID](
Account const& A1, Account const& A2, Env& env) -> bool {
MPTTester mpt(env, A1, {.holders = {A2}, .fund = false});
// completely omitted the tfMPTCanPrivacy flag here.
mpt.create({.flags = tfMPTCanTransfer});
@@ -3911,7 +3913,8 @@ class Invariants_test : public beast::unit_test::suite
return false;
sleIssuance->setFieldU64(
sfConfidentialOutstandingAmount, sleIssuance->getFieldU64(sfConfidentialOutstandingAmount) - 10);
sfConfidentialOutstandingAmount,
sleIssuance->getFieldU64(sfConfidentialOutstandingAmount) - 10);
ac.view().update(sleIssuance);
return true;
@@ -3923,7 +3926,8 @@ class Invariants_test : public beast::unit_test::suite
// badVersion
doInvariantCheck(
{"MPToken sfConfidentialBalanceVersion not updated when sfConfidentialBalanceSpending changed"},
{"MPToken sfConfidentialBalanceVersion not updated when sfConfidentialBalanceSpending "
"changed"},
[&mptID](Account const& A1, Account const& A2, ApplyContext& ac) {
auto sleToken = ac.view().peek(keylet::mptoken(mptID, A2.id()));
if (!sleToken)
@@ -3940,7 +3944,8 @@ class Invariants_test : public beast::unit_test::suite
precloseConfidential);
// Skipping Deleted MPTs (Issuance deleted)
auto const precloseOrphan = [&mptID](Account const& A1, Account const& A2, Env& env) -> bool {
auto const precloseOrphan = [&mptID](
Account const& A1, Account const& A2, Env& env) -> bool {
MPTTester mpt(env, A1, {.holders = {A2}, .fund = false});
mpt.create({.flags = tfMPTCanTransfer | tfMPTCanPrivacy});
mptID = mpt.issuanceID();

View File

@@ -46,7 +46,11 @@ MPTTester::makeHolders(std::vector<Account> const& holders)
}
MPTTester::MPTTester(Env& env, Account const& issuer, MPTInit const& arg)
: env_(env), issuer_(issuer), holders_(makeHolders(arg.holders)), auditor_(arg.auditor), close_(arg.close)
: env_(env)
, issuer_(issuer)
, holders_(makeHolders(arg.holders))
, auditor_(arg.auditor)
, close_(arg.close)
{
if (arg.fund)
{
@@ -465,7 +469,8 @@ MPTTester::set(MPTSet const& arg)
auto const auditorPubKey = getPubKey(*auditor_);
if (!auditorPubKey)
Throw<std::runtime_error>("MPTTester::set: auditor's pubkey is not set");
Throw<std::runtime_error>(
"MPTTester::set: auditor's pubkey is not set");
return strHex((*sle)[sfAuditorElGamalPublicKey]) == strHex(*auditorPubKey);
}
@@ -527,8 +532,9 @@ MPTTester::checkMPTokenOutstandingAmount(std::int64_t expectedAmount) const
[[nodiscard]] bool
MPTTester::checkIssuanceConfidentialBalance(std::int64_t expectedAmount) const
{
return forObject(
[&](SLEP const& sle) { return expectedAmount == (*sle)[~sfConfidentialOutstandingAmount].value_or(0); });
return forObject([&](SLEP const& sle) {
return expectedAmount == (*sle)[~sfConfidentialOutstandingAmount].value_or(0);
});
}
[[nodiscard]] bool
@@ -717,7 +723,8 @@ MPTTester::getClawbackProof(
return std::nullopt;
}
if (!secp256k1_ec_pubkey_parse(ctx, &c2, ciphertextBlob.data() + ecGamalEncryptedLength, ecGamalEncryptedLength))
if (!secp256k1_ec_pubkey_parse(
ctx, &c2, ciphertextBlob.data() + ecGamalEncryptedLength, ecGamalEncryptedLength))
{
return std::nullopt;
}
@@ -755,7 +762,8 @@ MPTTester::getSchnorrProof(Account const& account, uint256 const& ctxHash) const
Buffer proof(ecSchnorrProofLength);
if (secp256k1_mpt_pok_sk_prove(secp256k1Context(), proof.data(), &pk, privKey->data(), ctxHash.data()) != 1)
if (secp256k1_mpt_pok_sk_prove(
secp256k1Context(), proof.data(), &pk, privKey->data(), ctxHash.data()) != 1)
{
return std::nullopt;
}
@@ -810,7 +818,8 @@ MPTTester::getConfidentialSendProof(
return std::nullopt;
}
if (!secp256k1_ec_pubkey_parse(ctx, &c2_vec[i], ctData + ecGamalEncryptedLength, ecGamalEncryptedLength))
if (!secp256k1_ec_pubkey_parse(
ctx, &c2_vec[i], ctData + ecGamalEncryptedLength, ecGamalEncryptedLength))
return std::nullopt;
if (!secp256k1_ec_pubkey_parse(ctx, &pk_vec[i], recipient.publicKey.data(), ecPubKeyLength))
@@ -835,9 +844,13 @@ MPTTester::getConfidentialSendProof(
}
auto const amountLinkageProof = getAmountLinkageProof(
*senderPubKey, Buffer(blindingFactor.data(), ecBlindingFactorLength), contextHash, amountParams);
*senderPubKey,
Buffer(blindingFactor.data(), ecBlindingFactorLength),
contextHash,
amountParams);
auto const balanceLinkageProof = getBalanceLinkageProof(sender, contextHash, *senderPubKey, balanceParams);
auto const balanceLinkageProof =
getBalanceLinkageProof(sender, contextHash, *senderPubKey, balanceParams);
std::uint64_t const remainingBalance = balanceParams.amt - amount;
@@ -849,8 +862,10 @@ MPTTester::getConfidentialSendProof(
secp256k1_mpt_scalar_add(rho_rem, balanceParams.blindingFactor.data(), neg_rho_m);
// Generate bulletproof for the amount and remaining balance
Buffer const bulletproof =
getBulletproof({amount, remainingBalance}, {amountParams.blindingFactor, Buffer(rho_rem, 32)}, contextHash);
Buffer const bulletproof = getBulletproof(
{amount, remainingBalance},
{amountParams.blindingFactor, Buffer(rho_rem, 32)},
contextHash);
OPENSSL_cleanse(neg_rho_m, 32);
OPENSSL_cleanse(rho_rem, 32);
@@ -859,7 +874,8 @@ MPTTester::getConfidentialSendProof(
auto const sizeBalanceLinkage = balanceLinkageProof.size();
auto const sizeBulletproof = bulletproof.size();
size_t const proofSize = sizeEquality + sizeAmountLinkage + sizeBalanceLinkage + sizeBulletproof;
size_t const proofSize =
sizeEquality + sizeAmountLinkage + sizeBalanceLinkage + sizeBulletproof;
Buffer proof(proofSize);
auto ptr = proof.data();
@@ -907,7 +923,8 @@ MPTTester::getPedersenCommitment(std::uint64_t const amount, Buffer const& peder
// Serialize commitment to compressed format (33 bytes)
unsigned char compressedCommitment[ecPedersenCommitmentLength];
size_t outLen = ecPedersenCommitmentLength;
if (secp256k1_ec_pubkey_serialize(ctx, compressedCommitment, &outLen, &commitment, SECP256K1_EC_COMPRESSED) != 1 ||
if (secp256k1_ec_pubkey_serialize(
ctx, compressedCommitment, &outLen, &commitment, SECP256K1_EC_COMPRESSED) != 1 ||
outLen != ecPedersenCommitmentLength)
{
Throw<std::runtime_error>("Pedersen commitment serialization failed");
@@ -935,17 +952,20 @@ MPTTester::getConvertBackProof(
if (!holderPubKey)
return makeZeroBuffer(expectedProofLength);
Buffer const pedersenProof = getBalanceLinkageProof(holder, contextHash, *holderPubKey, pcParams);
Buffer const pedersenProof =
getBalanceLinkageProof(holder, contextHash, *holderPubKey, pcParams);
// Generate bulletproof for the remaining balance (balance - amount)
// Use the same blinding factor as the one used to generate the PC_balance
std::uint64_t const remainingBalance = pcParams.amt - amount;
Buffer const bulletproof = getBulletproof({remainingBalance}, {pcParams.blindingFactor}, contextHash);
Buffer const bulletproof =
getBulletproof({remainingBalance}, {pcParams.blindingFactor}, contextHash);
// Combine pedersen proof and bulletproof
Buffer combinedProof(pedersenProof.size() + bulletproof.size());
std::memcpy(combinedProof.data(), pedersenProof.data(), pedersenProof.size());
std::memcpy(combinedProof.data() + pedersenProof.size(), bulletproof.data(), bulletproof.size());
std::memcpy(
combinedProof.data() + pedersenProof.size(), bulletproof.data(), bulletproof.size());
return combinedProof;
}
@@ -959,13 +979,20 @@ MPTTester::getEncryptedBalance(Account const& account, EncryptedBalanceType opti
if (auto const sle = env_.le(keylet::mptoken(*id_, account.id())))
{
if (option == HOLDER_ENCRYPTED_INBOX && sle->isFieldPresent(sfConfidentialBalanceInbox))
return Buffer((*sle)[sfConfidentialBalanceInbox].data(), (*sle)[sfConfidentialBalanceInbox].size());
if (option == HOLDER_ENCRYPTED_SPENDING && sle->isFieldPresent(sfConfidentialBalanceSpending))
return Buffer((*sle)[sfConfidentialBalanceSpending].data(), (*sle)[sfConfidentialBalanceSpending].size());
return Buffer(
(*sle)[sfConfidentialBalanceInbox].data(),
(*sle)[sfConfidentialBalanceInbox].size());
if (option == HOLDER_ENCRYPTED_SPENDING &&
sle->isFieldPresent(sfConfidentialBalanceSpending))
return Buffer(
(*sle)[sfConfidentialBalanceSpending].data(),
(*sle)[sfConfidentialBalanceSpending].size());
if (option == ISSUER_ENCRYPTED_BALANCE && sle->isFieldPresent(sfIssuerEncryptedBalance))
return Buffer((*sle)[sfIssuerEncryptedBalance].data(), (*sle)[sfIssuerEncryptedBalance].size());
return Buffer(
(*sle)[sfIssuerEncryptedBalance].data(), (*sle)[sfIssuerEncryptedBalance].size());
if (option == AUDITOR_ENCRYPTED_BALANCE && sle->isFieldPresent(sfAuditorEncryptedBalance))
return Buffer((*sle)[sfAuditorEncryptedBalance].data(), (*sle)[sfAuditorEncryptedBalance].size());
return Buffer(
(*sle)[sfAuditorEncryptedBalance].data(), (*sle)[sfAuditorEncryptedBalance].size());
}
return {};
@@ -1065,7 +1092,8 @@ MPTTester::convert(MPTConvert const& arg)
std::optional<Buffer> auditorCiphertext;
Buffer blindingFactor;
fillConversionCiphertexts(arg, jv, holderCiphertext, issuerCiphertext, auditorCiphertext, blindingFactor);
fillConversionCiphertexts(
arg, jv, holderCiphertext, issuerCiphertext, auditorCiphertext, blindingFactor);
jv[sfBlindingFactor.jsonName] = strHex(blindingFactor);
if (arg.proof)
@@ -1076,7 +1104,8 @@ MPTTester::convert(MPTConvert const& arg)
// if fillSchnorrProof is explicitly set, follow its value;
// otherwise, default to generating the proof only if holder pub key is
// present.
auto const contextHash = getConvertContextHash(arg.account->id(), *id_, env_.seq(*arg.account));
auto const contextHash =
getConvertContextHash(arg.account->id(), *id_, env_.seq(*arg.account));
auto const proof = getSchnorrProof(*arg.account, contextHash);
if (proof)
@@ -1107,39 +1136,47 @@ MPTTester::convert(MPTConvert const& arg)
{
auto const postConfidentialOutstanding = getIssuanceConfidentialBalance();
env_.require(mptbalance(*this, *arg.account, holderAmt - *arg.amt));
env_.require(requireAny(
[&]() -> bool { return prevConfidentialOutstanding + *arg.amt == postConfidentialOutstanding; }));
env_.require(requireAny([&]() -> bool {
return prevConfidentialOutstanding + *arg.amt == postConfidentialOutstanding;
}));
auto const postInboxBalance = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_INBOX);
auto const postIssuerBalance = getDecryptedBalance(*arg.account, ISSUER_ENCRYPTED_BALANCE);
auto const postSpendingBalance = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const postSpendingBalance =
getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
if (!postInboxBalance || !postIssuerBalance || !postSpendingBalance)
Throw<std::runtime_error>("Failed to get post-convert balance");
if (arg.auditorEncryptedAmt || auditor_)
{
auto const postAuditorBalance = getDecryptedBalance(*arg.account, AUDITOR_ENCRYPTED_BALANCE);
auto const postAuditorBalance =
getDecryptedBalance(*arg.account, AUDITOR_ENCRYPTED_BALANCE);
if (!postAuditorBalance)
Throw<std::runtime_error>("Failed to get post-convert auditor balance");
// auditor's encrypted balance is updated correctly
env_.require(requireAny([&]() -> bool { return *prevAuditorBalance + *arg.amt == *postAuditorBalance; }));
env_.require(requireAny(
[&]() -> bool { return *prevAuditorBalance + *arg.amt == *postAuditorBalance; }));
}
// spending balance should not change
env_.require(requireAny([&]() -> bool { return *postSpendingBalance == *prevSpendingBalance; }));
env_.require(
requireAny([&]() -> bool { return *postSpendingBalance == *prevSpendingBalance; }));
// issuer's encrypted balance is updated correctly
env_.require(requireAny([&]() -> bool { return *prevIssuerBalance + *arg.amt == *postIssuerBalance; }));
env_.require(requireAny(
[&]() -> bool { return *prevIssuerBalance + *arg.amt == *postIssuerBalance; }));
// holder's inbox balance is updated correctly
env_.require(requireAny([&]() -> bool { return *prevInboxBalance + *arg.amt == *postInboxBalance; }));
env_.require(requireAny(
[&]() -> bool { return *prevInboxBalance + *arg.amt == *postInboxBalance; }));
// sum of holder's inbox and spending balance should equal to issuer's
// encrypted balance
env_.require(
requireAny([&]() -> bool { return *postInboxBalance + *postSpendingBalance == *postIssuerBalance; }));
env_.require(requireAny([&]() -> bool {
return *postInboxBalance + *postSpendingBalance == *postIssuerBalance;
}));
if (arg.holderPubKey)
{
@@ -1154,7 +1191,8 @@ MPTTester::convert(MPTConvert const& arg)
"MPTTester::convert: holder's pubkey is "
"not set");
return strHex((*sle)[sfHolderElGamalPublicKey]) == strHex(*holderPubKey);
return strHex((*sle)[sfHolderElGamalPublicKey]) ==
strHex(*holderPubKey);
}
return false;
},
@@ -1192,15 +1230,18 @@ MPTTester::send(MPTConfidentialSend const& arg)
jv[sfMPTokenIssuanceID] = to_string(*id_);
}
Buffer const blindingFactor = arg.blindingFactor ? *arg.blindingFactor : generateBlindingFactor();
Buffer const blindingFactor =
arg.blindingFactor ? *arg.blindingFactor : generateBlindingFactor();
// fill in the encrypted amounts if not provided
auto const senderAmt =
arg.senderEncryptedAmt ? *arg.senderEncryptedAmt : encryptAmount(*arg.account, *arg.amt, blindingFactor);
auto const destAmt =
arg.destEncryptedAmt ? *arg.destEncryptedAmt : encryptAmount(*arg.dest, *arg.amt, blindingFactor);
auto const issuerAmt =
arg.issuerEncryptedAmt ? *arg.issuerEncryptedAmt : encryptAmount(issuer_, *arg.amt, blindingFactor);
auto const senderAmt = arg.senderEncryptedAmt
? *arg.senderEncryptedAmt
: encryptAmount(*arg.account, *arg.amt, blindingFactor);
auto const destAmt = arg.destEncryptedAmt ? *arg.destEncryptedAmt
: encryptAmount(*arg.dest, *arg.amt, blindingFactor);
auto const issuerAmt = arg.issuerEncryptedAmt
? *arg.issuerEncryptedAmt
: encryptAmount(issuer_, *arg.amt, blindingFactor);
std::optional<Buffer> auditorAmt;
if (arg.auditorEncryptedAmt)
@@ -1279,8 +1320,8 @@ MPTTester::send(MPTConfidentialSend const& arg)
else
{
auto const version = getMPTokenVersion(*arg.account);
auto const ctxHash =
getSendContextHash(arg.account->id(), *id_, env_.seq(*arg.account), arg.dest->id(), version);
auto const ctxHash = getSendContextHash(
arg.account->id(), *id_, env_.seq(*arg.account), arg.dest->id(), version);
auto const nRecipients = getConfidentialRecipientCount(auditorAmt.has_value());
std::vector<ConfidentialRecipient> recipients;
@@ -1310,7 +1351,8 @@ MPTTester::send(MPTConfidentialSend const& arg)
recipients.push_back({Slice(*auditorPubKey), *auditorAmt});
}
auto const prevEncryptedSenderSpending = getEncryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const prevEncryptedSenderSpending =
getEncryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
std::optional<Buffer> proof;
@@ -1342,7 +1384,8 @@ MPTTester::send(MPTConfidentialSend const& arg)
else
{
size_t const sizeEquality = secp256k1_mpt_prove_same_plaintext_multi_size(nRecipients);
size_t const dummySize = sizeEquality + 2 * ecPedersenProofLength + ecDoubleBulletproofLength;
size_t const dummySize =
sizeEquality + 2 * ecPedersenProofLength + ecDoubleBulletproofLength;
jv[sfZKProof.jsonName] = strHex(makeZeroBuffer(dummySize));
}
@@ -1360,7 +1403,8 @@ MPTTester::send(MPTConfidentialSend const& arg)
// Sender's post confidential state
auto const postSenderInbox = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_INBOX);
auto const postSenderSpending = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const postSenderSpending =
getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const postSenderIssuer = getDecryptedBalance(*arg.account, ISSUER_ENCRYPTED_BALANCE);
if (!postSenderInbox || !postSenderSpending || !postSenderIssuer)
@@ -1384,44 +1428,56 @@ MPTTester::send(MPTConfidentialSend const& arg)
// Verify sender changes
env_.require(requireAny([&]() -> bool {
return *prevSenderSpending >= *arg.amt && *postSenderSpending == *prevSenderSpending - *arg.amt;
return *prevSenderSpending >= *arg.amt &&
*postSenderSpending == *prevSenderSpending - *arg.amt;
}));
env_.require(requireAny([&]() -> bool { return postSenderInbox == prevSenderInbox; }));
env_.require(requireAny([&]() -> bool {
return *prevSenderIssuer >= *arg.amt && *postSenderIssuer == *prevSenderIssuer - *arg.amt;
return *prevSenderIssuer >= *arg.amt &&
*postSenderIssuer == *prevSenderIssuer - *arg.amt;
}));
// Verify destination changes
env_.require(requireAny([&]() -> bool { return *postDestInbox == *prevDestInbox + *arg.amt; }));
env_.require(
requireAny([&]() -> bool { return *postDestInbox == *prevDestInbox + *arg.amt; }));
env_.require(requireAny([&]() -> bool { return *postDestSpending == *prevDestSpending; }));
env_.require(requireAny([&]() -> bool { return *postDestIssuer == *prevDestIssuer + *arg.amt; }));
env_.require(
requireAny([&]() -> bool { return *postDestIssuer == *prevDestIssuer + *arg.amt; }));
// Cross checks
env_.require(requireAny([&]() -> bool { return *postSenderInbox + *postSenderSpending == *postSenderIssuer; }));
env_.require(requireAny([&]() -> bool { return *postDestInbox + *postDestSpending == *postDestIssuer; }));
env_.require(requireAny(
[&]() -> bool { return *postSenderInbox + *postSenderSpending == *postSenderIssuer; }));
env_.require(requireAny(
[&]() -> bool { return *postDestInbox + *postDestSpending == *postDestIssuer; }));
// Version: sender increments by 1; receiver version is unchanged by incoming sends
env_.require(requireAny([&]() -> bool { return getMPTokenVersion(*arg.account) == prevSenderVersion + 1; }));
env_.require(requireAny([&]() -> bool { return getMPTokenVersion(*arg.dest) == prevDestVersion; }));
env_.require(requireAny(
[&]() -> bool { return getMPTokenVersion(*arg.account) == prevSenderVersion + 1; }));
env_.require(
requireAny([&]() -> bool { return getMPTokenVersion(*arg.dest) == prevDestVersion; }));
if (arg.auditorEncryptedAmt || auditor_)
{
auto const postSenderAuditor = getDecryptedBalance(*arg.account, AUDITOR_ENCRYPTED_BALANCE);
auto const postSenderAuditor =
getDecryptedBalance(*arg.account, AUDITOR_ENCRYPTED_BALANCE);
auto const postDestAuditor = getDecryptedBalance(*arg.dest, AUDITOR_ENCRYPTED_BALANCE);
if (!postSenderAuditor || !postDestAuditor)
Throw<std::runtime_error>("Failed to get Post-send balance");
env_.require(requireAny([&]() -> bool {
return *postSenderAuditor == *postSenderIssuer && *postDestAuditor == *postDestIssuer;
return *postSenderAuditor == *postSenderIssuer &&
*postDestAuditor == *postDestIssuer;
}));
// verify sender
env_.require(requireAny([&]() -> bool {
return prevSenderAuditor >= *arg.amt && *postSenderAuditor == *prevSenderAuditor - *arg.amt;
return prevSenderAuditor >= *arg.amt &&
*postSenderAuditor == *prevSenderAuditor - *arg.amt;
}));
// verify dest
env_.require(requireAny([&]() -> bool { return *postDestAuditor == *prevDestAuditor + *arg.amt; }));
env_.require(requireAny(
[&]() -> bool { return *postDestAuditor == *prevDestAuditor + *arg.amt; }));
}
}
}
@@ -1454,7 +1510,8 @@ MPTTester::confidentialClaw(MPTConfidentialClawback const& arg)
else
{
std::uint32_t const seq = env_.seq(account);
uint256 const contextHash = getClawbackContextHash(account.id(), *id_, seq, arg.holder->id());
uint256 const contextHash =
getClawbackContextHash(account.id(), *id_, seq, arg.holder->id());
auto const privKey = getPrivKey(account);
if (!privKey || privKey->size() != ecPrivKeyLength)
@@ -1483,18 +1540,24 @@ MPTTester::confidentialClaw(MPTConfidentialClawback const& arg)
env_.require(mptbalance(*this, *arg.holder, holderPubAmt));
// Verify COA and OA are reduced correctly
env_.require(requireAny([&]() -> bool { return prevCOA >= *arg.amt && postCOA == prevCOA - *arg.amt; }));
env_.require(requireAny([&]() -> bool { return prevOA >= *arg.amt && postOA == prevOA - *arg.amt; }));
env_.require(requireAny(
[&]() -> bool { return prevCOA >= *arg.amt && postCOA == prevCOA - *arg.amt; }));
env_.require(requireAny(
[&]() -> bool { return prevOA >= *arg.amt && postOA == prevOA - *arg.amt; }));
// Verify holder's confidential balances are zeroed out
env_.require(
requireAny([&]() -> bool { return getDecryptedBalance(*arg.holder, HOLDER_ENCRYPTED_INBOX) == 0; }));
env_.require(
requireAny([&]() -> bool { return getDecryptedBalance(*arg.holder, HOLDER_ENCRYPTED_SPENDING) == 0; }));
env_.require(
requireAny([&]() -> bool { return getDecryptedBalance(*arg.holder, ISSUER_ENCRYPTED_BALANCE) == 0; }));
env_.require(
requireAny([&]() -> bool { return getDecryptedBalance(*arg.holder, AUDITOR_ENCRYPTED_BALANCE) == 0; }));
env_.require(requireAny([&]() -> bool {
return getDecryptedBalance(*arg.holder, HOLDER_ENCRYPTED_INBOX) == 0;
}));
env_.require(requireAny([&]() -> bool {
return getDecryptedBalance(*arg.holder, HOLDER_ENCRYPTED_SPENDING) == 0;
}));
env_.require(requireAny([&]() -> bool {
return getDecryptedBalance(*arg.holder, ISSUER_ENCRYPTED_BALANCE) == 0;
}));
env_.require(requireAny([&]() -> bool {
return getDecryptedBalance(*arg.holder, AUDITOR_ENCRYPTED_BALANCE) == 0;
}));
// Verify version is incremented
env_.require(requireAny([&]() -> bool { return postVersion == prevVersion + 1; }));
@@ -1546,7 +1609,8 @@ MPTTester::getPrivKey(Account const& account) const
}
Buffer
MPTTester::encryptAmount(Account const& account, uint64_t const amt, Buffer const& blindingFactor) const
MPTTester::encryptAmount(Account const& account, uint64_t const amt, Buffer const& blindingFactor)
const
{
if (auto const pubKey = getPubKey(account))
{
@@ -1637,20 +1701,24 @@ MPTTester::mergeInbox(MPTMergeInbox const& arg)
if (submit(arg, jv) == tesSUCCESS)
{
auto const postInboxBalance = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_INBOX);
auto const postSpendingBalance = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const postSpendingBalance =
getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const postIssuerBalance = getDecryptedBalance(*arg.account, ISSUER_ENCRYPTED_BALANCE);
if (!postInboxBalance || !postSpendingBalance || !postIssuerBalance)
Throw<std::runtime_error>("Failed to get post-mergeInbox balances");
env_.require(requireAny([&]() -> bool {
return *postSpendingBalance == *prevInboxBalance + *prevSpendingBalance && *postInboxBalance == 0;
return *postSpendingBalance == *prevInboxBalance + *prevSpendingBalance &&
*postInboxBalance == 0;
}));
env_.require(requireAny([&]() -> bool { return *prevIssuerBalance == *postIssuerBalance; }));
env_.require(
requireAny([&]() -> bool { return *postSpendingBalance + *postInboxBalance == *postIssuerBalance; }));
requireAny([&]() -> bool { return *prevIssuerBalance == *postIssuerBalance; }));
env_.require(requireAny([&]() -> bool {
return *postSpendingBalance + *postInboxBalance == *postIssuerBalance;
}));
}
}
@@ -1711,7 +1779,8 @@ MPTTester::convertBack(MPTConvertBack const& arg)
std::optional<Buffer> auditorCiphertext;
Buffer blindingFactor;
fillConversionCiphertexts(arg, jv, holderCiphertext, issuerCiphertext, auditorCiphertext, blindingFactor);
fillConversionCiphertexts(
arg, jv, holderCiphertext, issuerCiphertext, auditorCiphertext, blindingFactor);
jv[sfBlindingFactor] = strHex(blindingFactor);
@@ -1739,8 +1808,10 @@ MPTTester::convertBack(MPTConvertBack const& arg)
// if the caller generated ciphertexts themselves, they should also
// generate the proof themselves from the blinding factor
uint256 const contextHash = getConvertBackContextHash(arg.account->id(), *id_, env_.seq(*arg.account), version);
auto const prevEncryptedSpendingBalance = getEncryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
uint256 const contextHash =
getConvertBackContextHash(arg.account->id(), *id_, env_.seq(*arg.account), version);
auto const prevEncryptedSpendingBalance =
getEncryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
Buffer proof;
// generate a dummy proof if no encrypted amount field, so that other
@@ -1778,40 +1849,47 @@ MPTTester::convertBack(MPTConvertBack const& arg)
{
auto const postConfidentialOutstanding = getIssuanceConfidentialBalance();
env_.require(mptbalance(*this, *arg.account, holderAmt + *arg.amt));
env_.require(requireAny(
[&]() -> bool { return prevConfidentialOutstanding - *arg.amt == postConfidentialOutstanding; }));
env_.require(requireAny([&]() -> bool {
return prevConfidentialOutstanding - *arg.amt == postConfidentialOutstanding;
}));
auto const postInboxBalance = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_INBOX);
auto const postIssuerBalance = getDecryptedBalance(*arg.account, ISSUER_ENCRYPTED_BALANCE);
auto const postSpendingBalance = getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
auto const postSpendingBalance =
getDecryptedBalance(*arg.account, HOLDER_ENCRYPTED_SPENDING);
if (!postInboxBalance || !postIssuerBalance || !postSpendingBalance)
Throw<std::runtime_error>("Failed to get post-convertBack balance");
if (arg.auditorEncryptedAmt || auditor_)
{
auto const postAuditorBalance = getDecryptedBalance(*arg.account, AUDITOR_ENCRYPTED_BALANCE);
auto const postAuditorBalance =
getDecryptedBalance(*arg.account, AUDITOR_ENCRYPTED_BALANCE);
if (!postAuditorBalance)
Throw<std::runtime_error>("Failed to get post-convertBack balance");
// auditor's encrypted balance is updated correctly
env_.require(requireAny([&]() -> bool { return *prevAuditorBalance - *arg.amt == *postAuditorBalance; }));
env_.require(requireAny(
[&]() -> bool { return *prevAuditorBalance - *arg.amt == *postAuditorBalance; }));
}
// inbox balance should not change
env_.require(requireAny([&]() -> bool { return *postInboxBalance == *prevInboxBalance; }));
// issuer's encrypted balance is updated correctly
env_.require(requireAny([&]() -> bool { return *prevIssuerBalance - *arg.amt == *postIssuerBalance; }));
env_.require(requireAny(
[&]() -> bool { return *prevIssuerBalance - *arg.amt == *postIssuerBalance; }));
// holder's spending balance is updated correctly
env_.require(requireAny([&]() -> bool { return *prevSpendingBalance - *arg.amt == *postSpendingBalance; }));
env_.require(requireAny(
[&]() -> bool { return *prevSpendingBalance - *arg.amt == *postSpendingBalance; }));
// sum of holder's inbox and spending balance should equal to issuer's
// encrypted balance
env_.require(
requireAny([&]() -> bool { return *postInboxBalance + *postSpendingBalance == *postIssuerBalance; }));
env_.require(requireAny([&]() -> bool {
return *postInboxBalance + *postSpendingBalance == *postIssuerBalance;
}));
}
}
@@ -1823,8 +1901,10 @@ MPTTester::getAmountLinkageProof(
PedersenProofParams const& params) const
{
if (params.blindingFactor.size() != ecBlindingFactorLength ||
params.pedersenCommitment.size() != ecPedersenCommitmentLength || pubKey.size() != ecPubKeyLength ||
params.encryptedAmt.size() != ecGamalEncryptedTotalLength || blindingFactor.size() != ecBlindingFactorLength)
params.pedersenCommitment.size() != ecPedersenCommitmentLength ||
pubKey.size() != ecPubKeyLength ||
params.encryptedAmt.size() != ecGamalEncryptedTotalLength ||
blindingFactor.size() != ecBlindingFactorLength)
return makeZeroBuffer(ecPedersenProofLength);
secp256k1_pubkey c1, c2;
@@ -1841,7 +1921,8 @@ MPTTester::getAmountLinkageProof(
return Buffer();
secp256k1_pubkey pcm;
if (secp256k1_ec_pubkey_parse(ctx, &pcm, params.pedersenCommitment.data(), ecPedersenCommitmentLength) != 1)
if (secp256k1_ec_pubkey_parse(
ctx, &pcm, params.pedersenCommitment.data(), ecPedersenCommitmentLength) != 1)
return Buffer();
Buffer proof(ecPedersenProofLength);
@@ -1871,7 +1952,8 @@ MPTTester::getBalanceLinkageProof(
PedersenProofParams const& params) const
{
if (params.blindingFactor.size() != ecBlindingFactorLength ||
params.pedersenCommitment.size() != ecPedersenCommitmentLength || pubKey.size() != ecPubKeyLength ||
params.pedersenCommitment.size() != ecPedersenCommitmentLength ||
pubKey.size() != ecPubKeyLength ||
params.encryptedAmt.size() != ecGamalEncryptedTotalLength)
return makeZeroBuffer(ecPedersenProofLength);
@@ -1889,7 +1971,8 @@ MPTTester::getBalanceLinkageProof(
return Buffer();
secp256k1_pubkey pcm;
if (secp256k1_ec_pubkey_parse(ctx, &pcm, params.pedersenCommitment.data(), ecPedersenCommitmentLength) != 1)
if (secp256k1_ec_pubkey_parse(
ctx, &pcm, params.pedersenCommitment.data(), ecPedersenCommitmentLength) != 1)
return Buffer();
Buffer proof(ecPedersenProofLength);
@@ -1935,7 +2018,9 @@ MPTTester::getBulletproof(
std::vector<unsigned char> blindingsFlat(m * ecBlindingFactorLength);
for (std::size_t i = 0; i < m; ++i)
std::memcpy(
blindingsFlat.data() + i * ecBlindingFactorLength, blindingFactors[i].data(), ecBlindingFactorLength);
blindingsFlat.data() + i * ecBlindingFactorLength,
blindingFactors[i].data(),
ecBlindingFactorLength);
secp256k1_pubkey pk_base;
if (secp256k1_mpt_get_h_generator(secp256k1Context(), &pk_base) != 1)
@@ -1958,7 +2043,8 @@ MPTTester::getBulletproof(
Throw<std::runtime_error>("Bulletproof generation failed");
}
std::size_t const expectedLen = (m == 1) ? ecSingleBulletproofLength : ecDoubleBulletproofLength;
std::size_t const expectedLen =
(m == 1) ? ecSingleBulletproofLength : ecDoubleBulletproofLength;
if (proofLen != expectedLen)
Throw<std::runtime_error>("Unexpected bulletproof length");

View File

@@ -365,7 +365,8 @@ public:
checkIssuanceConfidentialBalance(std::int64_t expectedAmount) const;
[[nodiscard]] bool
checkFlags(uint32_t const expectedFlags, std::optional<Account> const& holder = std::nullopt) const;
checkFlags(uint32_t const expectedFlags, std::optional<Account> const& holder = std::nullopt)
const;
[[nodiscard]] bool
checkMetadata(std::string const& metadata) const;
@@ -420,7 +421,9 @@ public:
getIssuanceConfidentialBalance() const;
std::optional<Buffer>
getEncryptedBalance(Account const& account, EncryptedBalanceType option = HOLDER_ENCRYPTED_INBOX) const;
getEncryptedBalance(
Account const& account,
EncryptedBalanceType option = HOLDER_ENCRYPTED_INBOX) const;
MPT
operator[](std::string const& name) const;
@@ -455,8 +458,11 @@ public:
getIssuanceOutstandingBalance() const;
std::optional<Buffer>
getClawbackProof(Account const& holder, std::uint64_t amount, Buffer const& privateKey, uint256 const& txHash)
const;
getClawbackProof(
Account const& holder,
std::uint64_t amount,
Buffer const& privateKey,
uint256 const& txHash) const;
std::optional<Buffer>
getSchnorrProof(Account const& account, uint256 const& ctxHash) const;