From b0386622cad367da19620a179bbef9429d0ba11a Mon Sep 17 00:00:00 2001 From: yinyiqian1 Date: Thu, 23 Apr 2026 01:19:27 -0400 Subject: [PATCH] fix clang-tidy --- src/libxrpl/protocol/ConfidentialTransfer.cpp | 18 ++ src/libxrpl/tx/invariants/MPTInvariant.cpp | 2 + .../token/ConfidentialMPTClawback.cpp | 11 +- .../token/ConfidentialMPTConvert.cpp | 20 +- .../token/ConfidentialMPTConvertBack.cpp | 21 +- .../token/ConfidentialMPTMergeInbox.cpp | 11 +- .../transactors/token/ConfidentialMPTSend.cpp | 25 +- .../token/MPTokenIssuanceCreate.cpp | 7 +- .../transactors/token/MPTokenIssuanceSet.cpp | 17 +- src/test/app/ConfidentialTransfer_test.cpp | 48 +++- src/test/jtx/impl/mpt.cpp | 229 ++++++++++++++++-- src/test/jtx/mpt.h | 12 +- 12 files changed, 359 insertions(+), 62 deletions(-) diff --git a/src/libxrpl/protocol/ConfidentialTransfer.cpp b/src/libxrpl/protocol/ConfidentialTransfer.cpp index 4acb9d5fe2..4d70c3d823 100644 --- a/src/libxrpl/protocol/ConfidentialTransfer.cpp +++ b/src/libxrpl/protocol/ConfidentialTransfer.cpp @@ -1,11 +1,29 @@ #include + +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include +#include #include +#include +#include +#include +#include +#include +#include + namespace xrpl { /** diff --git a/src/libxrpl/tx/invariants/MPTInvariant.cpp b/src/libxrpl/tx/invariants/MPTInvariant.cpp index bcce1c2533..229f5572c0 100644 --- a/src/libxrpl/tx/invariants/MPTInvariant.cpp +++ b/src/libxrpl/tx/invariants/MPTInvariant.cpp @@ -1,7 +1,9 @@ #include #include +#include #include +#include #include #include #include diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp index c9c570ab74..cd5bdf2937 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTClawback.cpp @@ -1,12 +1,19 @@ #include -#include +#include +#include #include #include #include #include +#include +#include #include -#include +#include +#include + +#include +#include namespace xrpl { diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp index ae10a95e49..757ee06828 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvert.cpp @@ -1,13 +1,21 @@ #include -#include +#include +#include #include #include #include #include #include +#include +#include #include -#include +#include +#include + +#include +#include +#include namespace xrpl { @@ -157,15 +165,17 @@ ConfidentialMPTConvert::preclaim(PreclaimContext const& ctx) { auditor.emplace( ConfidentialRecipient{ - (*sleIssuance)[sfAuditorEncryptionKey], ctx.tx[sfAuditorEncryptedAmount]}); + .publicKey = (*sleIssuance)[sfAuditorEncryptionKey], + .encryptedAmount = ctx.tx[sfAuditorEncryptedAmount]}); } auto const blindingFactor = ctx.tx[sfBlindingFactor]; if (auto const ter = verifyRevealedAmount( amount, Slice(blindingFactor.data(), blindingFactor.size()), - {holderPubKey, ctx.tx[sfHolderEncryptedAmount]}, - {(*sleIssuance)[sfIssuerEncryptionKey], ctx.tx[sfIssuerEncryptedAmount]}, + {.publicKey = holderPubKey, .encryptedAmount = ctx.tx[sfHolderEncryptedAmount]}, + {.publicKey = (*sleIssuance)[sfIssuerEncryptionKey], + .encryptedAmount = ctx.tx[sfIssuerEncryptedAmount]}, auditor); !isTesSuccess(ter)) { diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp index 44fbf98a16..66b83a1d8f 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTConvertBack.cpp @@ -1,15 +1,22 @@ #include -#include +#include +#include #include #include #include #include #include +#include +#include +#include #include -#include +#include +#include -#include +#include +#include +#include namespace xrpl { @@ -82,7 +89,8 @@ verifyProofs( { auditor.emplace( ConfidentialRecipient{ - (*issuance)[sfAuditorEncryptionKey], tx[sfAuditorEncryptedAmount]}); + .publicKey = (*issuance)[sfAuditorEncryptionKey], + .encryptedAmount = tx[sfAuditorEncryptedAmount]}); } // Run all verifications before returning any error to prevent timing attacks @@ -92,8 +100,9 @@ verifyProofs( if (auto const ter = verifyRevealedAmount( amount, Slice(blindingFactor.data(), blindingFactor.size()), - {holderPubKey, tx[sfHolderEncryptedAmount]}, - {(*issuance)[sfIssuerEncryptionKey], tx[sfIssuerEncryptedAmount]}, + {.publicKey = holderPubKey, .encryptedAmount = tx[sfHolderEncryptedAmount]}, + {.publicKey = (*issuance)[sfIssuerEncryptionKey], + .encryptedAmount = tx[sfIssuerEncryptedAmount]}, auditor); !isTesSuccess(ter)) { diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp index ddbbfd6a96..0874a41321 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTMergeInbox.cpp @@ -1,13 +1,20 @@ #include -#include +#include +#include #include #include #include #include #include +#include +#include #include -#include +#include +#include + +#include +#include namespace xrpl { diff --git a/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp b/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp index 3ff65d37a3..6fe98c7687 100644 --- a/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp +++ b/src/libxrpl/tx/transactors/token/ConfidentialMPTSend.cpp @@ -1,14 +1,21 @@ #include -#include +#include #include #include #include #include #include #include +#include +#include #include -#include +#include +#include + +#include +#include +#include namespace xrpl { @@ -86,9 +93,12 @@ verifySendProofs( std::optional auditor; if (hasAuditor) + { auditor.emplace( ConfidentialRecipient{ - (*sleIssuance)[sfAuditorEncryptionKey], ctx.tx[sfAuditorEncryptedAmount]}); + .publicKey = (*sleIssuance)[sfAuditorEncryptionKey], + .encryptedAmount = ctx.tx[sfAuditorEncryptedAmount]}); + } auto const contextHash = getSendContextHash( ctx.tx[sfAccount], @@ -99,9 +109,12 @@ verifySendProofs( return verifySendProof( ctx.tx[sfZKProof], - {(*sleSenderMPToken)[sfHolderEncryptionKey], ctx.tx[sfSenderEncryptedAmount]}, - {(*sleDestinationMPToken)[sfHolderEncryptionKey], ctx.tx[sfDestinationEncryptedAmount]}, - {(*sleIssuance)[sfIssuerEncryptionKey], ctx.tx[sfIssuerEncryptedAmount]}, + {.publicKey = (*sleSenderMPToken)[sfHolderEncryptionKey], + .encryptedAmount = ctx.tx[sfSenderEncryptedAmount]}, + {.publicKey = (*sleDestinationMPToken)[sfHolderEncryptionKey], + .encryptedAmount = ctx.tx[sfDestinationEncryptedAmount]}, + {.publicKey = (*sleIssuance)[sfIssuerEncryptionKey], + .encryptedAmount = ctx.tx[sfIssuerEncryptedAmount]}, auditor, (*sleSenderMPToken)[sfConfidentialBalanceSpending], ctx.tx[sfAmountCommitment], diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp index ff6401d203..01d51b9239 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp @@ -42,11 +42,8 @@ MPTokenIssuanceCreate::checkExtraFeatures(PreflightContext const& ctx) // can not set tmfMPTCannotMutateCanConfidentialAmount without featureConfidentialTransfer auto const mutableFlags = ctx.tx[~sfMutableFlags]; - if (mutableFlags && (*mutableFlags & tmfMPTCannotMutateCanConfidentialAmount) && - !ctx.rules.enabled(featureConfidentialTransfer)) - return false; - - return true; + return !mutableFlags || ((*mutableFlags & tmfMPTCannotMutateCanConfidentialAmount) == 0u) || + ctx.rules.enabled(featureConfidentialTransfer); } std::uint32_t diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp index e1137d93b3..ea9c6c9a97 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp @@ -98,7 +98,8 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx) auto const txFlags = ctx.tx.getFlags(); auto const mutatePrivacy = mutableFlags && - ((*mutableFlags & (tmfMPTSetCanConfidentialAmount | tmfMPTClearCanConfidentialAmount))); + (((*mutableFlags & (tmfMPTSetCanConfidentialAmount | tmfMPTClearCanConfidentialAmount))) != + 0u); auto const hasDomain = ctx.tx.isFieldPresent(sfDomainID); auto const hasHolder = ctx.tx.isFieldPresent(sfHolder); @@ -176,7 +177,7 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx) // Cannot set keys while clearing confidential amount if ((hasIssuerElGamalKey || hasAuditorElGamalKey) && mutableFlags && - (*mutableFlags & tmfMPTClearCanConfidentialAmount)) + ((*mutableFlags & tmfMPTClearCanConfidentialAmount) != 0u)) return temINVALID_FLAG; if (hasIssuerElGamalKey && !isValidCompressedECPoint(ctx.tx[sfIssuerEncryptionKey])) @@ -291,8 +292,14 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) })) return tecNO_PERMISSION; - if ((*mutableFlags & tmfMPTSetCanConfidentialAmount) || - (*mutableFlags & tmfMPTClearCanConfidentialAmount)) + // Clearing lsfMPTRequireAuth is invalid when the issuance already has + // a DomainID set, because a DomainID requires RequireAuth to be active. + if ((*mutableFlags & tmfMPTClearRequireAuth) != 0u && + sleMptIssuance->isFieldPresent(sfDomainID)) + return tecNO_PERMISSION; + + if (((*mutableFlags & tmfMPTSetCanConfidentialAmount) != 0u) || + ((*mutableFlags & tmfMPTClearCanConfidentialAmount) != 0u)) { std::uint64_t const confidentialOA = (*sleMptIssuance)[~sfConfidentialOutstandingAmount].value_or(0); @@ -336,7 +343,7 @@ MPTokenIssuanceSet::preclaim(PreclaimContext const& ctx) // Check if the transaction is enabling confidential amounts bool const enablesConfidentialAmount = - mutableFlags && (*mutableFlags & tmfMPTSetCanConfidentialAmount); + mutableFlags && ((*mutableFlags & tmfMPTSetCanConfidentialAmount) != 0u); // Encryption keys can only be set if confidential amounts are already // enabled on the issuance OR if the transaction is enabling it diff --git a/src/test/app/ConfidentialTransfer_test.cpp b/src/test/app/ConfidentialTransfer_test.cpp index 321464167f..8fe93d5d19 100644 --- a/src/test/app/ConfidentialTransfer_test.cpp +++ b/src/test/app/ConfidentialTransfer_test.cpp @@ -1,12 +1,44 @@ -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include +#include +#include +#include +#include -#include +#include +#include +#include +#include +#include +#include +#include +#include namespace xrpl { @@ -70,7 +102,7 @@ class ConfidentialTransfer_test : public beast::unit_test::suite return trivialCommitment; } - std::string + static std::string getTrivialSendProofHex() { Buffer buf(ecSendProofLength); @@ -4259,7 +4291,7 @@ class ConfidentialTransfer_test : public beast::unit_test::suite }); // Bob authorizes the credential type from dpIssuer - env(deposit::authCredentials(bob, {{dpIssuer, credType}})); + env(deposit::authCredentials(bob, {{.issuer = dpIssuer, .credType = credType}})); env.close(); // Carol still cannot send without including credential @@ -4330,7 +4362,7 @@ class ConfidentialTransfer_test : public beast::unit_test::suite }); // Bob authorizes the credential type - env(deposit::authCredentials(bob, {{dpIssuer, credType}})); + env(deposit::authCredentials(bob, {{.issuer = dpIssuer, .credType = credType}})); env.close(); // Now Carol can send with credentials @@ -5383,12 +5415,14 @@ class ConfidentialTransfer_test : public beast::unit_test::suite auto holderPubKeySet = false; auto verifyToggle = [&](TER expectedResult, uint64_t amt) { if (!holderPubKeySet) + { mptAlice.convert({ .account = bob, .amt = amt, .holderPubKey = mptAlice.getPubKey(bob), .err = expectedResult, }); + } else { mptAlice.convert({ @@ -7354,7 +7388,7 @@ class ConfidentialTransfer_test : public beast::unit_test::suite // alice is issuer; bob has 'bobAmt' in confidential spending; carol has // 'carolAmt' in confidential spending; dave is initialised with pubkey but // zero spending/inbox. - void + static void setupBatchEnv( test::jtx::MPTTester& mpt, test::jtx::Account const& alice, diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index 60a60ee97c..1670440243 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -5,12 +5,13 @@ #include #include #include -#include #include #include #include #include +#include +#include #include #include #include @@ -32,9 +33,15 @@ #include +#include +#include + #include +#include #include +#include #include +#include #include #include #include @@ -450,7 +457,7 @@ MPTTester::set(MPTSet const& arg) .auditorPubKey = arg.auditorPubKey}); if (submit(arg, jv) == tesSUCCESS && ((arg.flags.value_or(0) != 0u) || arg.mutableFlags)) { - if ((arg.flags.value_or(0) || arg.mutableFlags)) + if (((arg.flags.value_or(0) != 0u) || arg.mutableFlags)) { auto require = [&](std::optional const& holder, bool unchanged) { auto flags = getFlags(holder); @@ -549,8 +556,10 @@ MPTTester::set(MPTSet const& arg) { auto const issuerPubKey = getPubKey(issuer_); if (!issuerPubKey) + { Throw( "MPTTester::set: issuer's pubkey is not set"); + } return strHex((*sle)[sfIssuerEncryptionKey]) == strHex(*issuerPubKey); } @@ -570,8 +579,10 @@ MPTTester::set(MPTSet const& arg) auto const auditorPubKey = getPubKey(*auditor_); if (!auditorPubKey) + { Throw( "MPTTester::set: auditor's pubkey is not set"); + } return strHex((*sle)[sfAuditorEncryptionKey]) == strHex(*auditorPubKey); } @@ -987,20 +998,28 @@ 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()); + } if (option == ISSUER_ENCRYPTED_BALANCE && sle->isFieldPresent(sfIssuerEncryptedBalance)) + { 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 {}; @@ -1046,25 +1065,37 @@ MPTTester::fillConversionCiphertexts( // Handle Holder if (arg.holderEncryptedAmt) + { holderCiphertext = *arg.holderEncryptedAmt; + } else + { holderCiphertext = encryptAmount(*arg.account, *arg.amt, blindingFactor); + } jv[sfHolderEncryptedAmount.jsonName] = strHex(holderCiphertext); // Handle Issuer if (arg.issuerEncryptedAmt) + { issuerCiphertext = *arg.issuerEncryptedAmt; + } else + { issuerCiphertext = encryptAmount(issuer_, *arg.amt, blindingFactor); + } jv[sfIssuerEncryptedAmount.jsonName] = strHex(issuerCiphertext); // Handle Auditor if (arg.auditorEncryptedAmt) + { auditorCiphertext = *arg.auditorEncryptedAmt; + } else if (auditor_.has_value() && *arg.fillAuditorEncryptedAmt) + { auditorCiphertext = encryptAmount(*auditor_, *arg.amt, blindingFactor); + } // Update auditor JSON only if ciphertext exists if (auditorCiphertext) @@ -1076,13 +1107,19 @@ MPTTester::convert(MPTConvert const& arg) { Json::Value jv; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } jv[jss::TransactionType] = jss::ConfidentialMPTConvert; if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -1105,7 +1142,9 @@ MPTTester::convert(MPTConvert const& arg) jv[sfBlindingFactor.jsonName] = strHex(blindingFactor); if (arg.proof) + { jv[sfZKProof.jsonName] = *arg.proof; + } else if (arg.fillSchnorrProof.value_or(arg.holderPubKey.has_value())) { // whether to automatically generate and attach a Schnorr proof: @@ -1117,9 +1156,13 @@ MPTTester::convert(MPTConvert const& arg) auto const proof = getSchnorrProof(*arg.account, contextHash); if (proof) + { jv[sfZKProof.jsonName] = strHex(*proof); + } else + { jv[sfZKProof.jsonName] = strHex(makeZeroBuffer(ecSchnorrProofLength)); + } } auto const holderAmt = getBalance(*arg.account); @@ -1195,9 +1238,11 @@ MPTTester::convert(MPTConvert const& arg) { auto const holderPubKey = getPubKey(*arg.account); if (!holderPubKey) + { Throw( "MPTTester::convert: holder's pubkey is " "not set"); + } return strHex((*sle)[sfHolderEncryptionKey]) == strHex(*holderPubKey); } @@ -1214,13 +1259,19 @@ MPTTester::convertJV(MPTConvert const& arg, std::uint32_t seq) { Json::Value jv; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } jv[jss::TransactionType] = jss::ConfidentialMPTConvert; if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -1244,15 +1295,21 @@ MPTTester::convertJV(MPTConvert const& arg, std::uint32_t seq) jv[sfBlindingFactor.jsonName] = strHex(blindingFactor); if (arg.proof) + { jv[sfZKProof.jsonName] = *arg.proof; + } else if (arg.fillSchnorrProof.value_or(arg.holderPubKey.has_value())) { auto const contextHash = getConvertContextHash(arg.account->id(), *id_, seq); auto const proof = getSchnorrProof(*arg.account, contextHash); if (proof) + { jv[sfZKProof.jsonName] = strHex(*proof); + } else + { jv[sfZKProof.jsonName] = strHex(makeZeroBuffer(ecSchnorrProofLength)); + } } return jv; @@ -1265,20 +1322,30 @@ MPTTester::send(MPTConfidentialSend const& arg) jv[jss::TransactionType] = jss::ConfidentialMPTSend; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } if (arg.dest) + { jv[sfDestination] = arg.dest->human(); + } else + { Throw("Destination not specified"); + } if (!arg.amt) Throw("Amount not specified for testing purposes"); if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -1301,9 +1368,13 @@ MPTTester::send(MPTConfidentialSend const& arg) std::optional auditorAmt; if (arg.auditorEncryptedAmt) + { auditorAmt = arg.auditorEncryptedAmt; + } else if (auditor_.has_value() && *arg.fillAuditorEncryptedAmt) + { auditorAmt = encryptAmount(*auditor_, *arg.amt, blindingFactor); + } jv[sfSenderEncryptedAmount] = strHex(senderAmt); jv[sfDestinationEncryptedAmount] = strHex(destAmt); @@ -1358,23 +1429,33 @@ MPTTester::send(MPTConfidentialSend const& arg) // for each would cause proof verification to fail. Buffer amountCommitment, balanceCommitment; if (arg.amountCommitment) + { amountCommitment = *arg.amountCommitment; + } else + { amountCommitment = getPedersenCommitment(*arg.amt, blindingFactor); + } jv[sfAmountCommitment] = strHex(amountCommitment); auto const balanceBlindingFactor = generateBlindingFactor(); if (arg.balanceCommitment) + { balanceCommitment = *arg.balanceCommitment; + } else + { balanceCommitment = getPedersenCommitment(*prevSenderSpending, balanceBlindingFactor); + } jv[sfBalanceCommitment] = strHex(balanceCommitment); // Fill in the proof if not provided if (arg.proof) + { jv[sfZKProof] = *arg.proof; + } else { auto const version = getMPTokenVersion(*arg.account); @@ -1391,11 +1472,11 @@ MPTTester::send(MPTConfidentialSend const& arg) // If a key is missing, we skip adding the recipient. This intentionally // causes proof generation to fail, triggering the dummy proof fallback. if (senderPubKey) - recipients.push_back({Slice(*senderPubKey), senderAmt}); + recipients.push_back({.publicKey = Slice(*senderPubKey), .encryptedAmount = senderAmt}); if (destPubKey) - recipients.push_back({Slice(*destPubKey), destAmt}); + recipients.push_back({.publicKey = Slice(*destPubKey), .encryptedAmount = destAmt}); if (issuerPubKey) - recipients.push_back({Slice(*issuerPubKey), issuerAmt}); + recipients.push_back({.publicKey = Slice(*issuerPubKey), .encryptedAmount = issuerAmt}); std::optional auditorPubKey; if (auditorAmt) @@ -1405,7 +1486,10 @@ MPTTester::send(MPTConfidentialSend const& arg) auditorPubKey = getPubKey(*auditor_); if (auditorPubKey) - recipients.push_back({Slice(*auditorPubKey), *auditorAmt}); + { + recipients.push_back( + {.publicKey = Slice(*auditorPubKey), .encryptedAmount = *auditorAmt}); + } } auto const prevEncryptedSenderSpending = @@ -1425,15 +1509,20 @@ MPTTester::send(MPTConfidentialSend const& arg) recipients, blindingFactor, ctxHash, - {amountCommitment, *arg.amt, senderAmt, blindingFactor}, - {balanceCommitment, - *prevSenderSpending, - *prevEncryptedSenderSpending, - balanceBlindingFactor}); + {.pedersenCommitment = amountCommitment, + .amt = *arg.amt, + .encryptedAmt = senderAmt, + .blindingFactor = blindingFactor}, + {.pedersenCommitment = balanceCommitment, + .amt = *prevSenderSpending, + .encryptedAmt = *prevEncryptedSenderSpending, + .blindingFactor = balanceBlindingFactor}); } if (proof) + { jv[sfZKProof.jsonName] = strHex(*proof); + } else { jv[sfZKProof.jsonName] = strHex(makeZeroBuffer(ecSendProofLength)); @@ -1541,20 +1630,30 @@ MPTTester::sendJV( jv[jss::TransactionType] = jss::ConfidentialMPTSend; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } if (arg.dest) + { jv[sfDestination] = arg.dest->human(); + } else + { Throw("Destination not specified"); + } if (!arg.amt) Throw("Amount not specified for testing purposes"); if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -1576,9 +1675,13 @@ MPTTester::sendJV( std::optional auditorAmt; if (arg.auditorEncryptedAmt) + { auditorAmt = arg.auditorEncryptedAmt; + } else if (auditor_.has_value() && *arg.fillAuditorEncryptedAmt) + { auditorAmt = encryptAmount(*auditor_, *arg.amt, blindingFactor); + } jv[sfSenderEncryptedAmount] = strHex(senderAmt); jv[sfDestinationEncryptedAmount] = strHex(destAmt); @@ -1616,22 +1719,32 @@ MPTTester::sendJV( // encryption blinding factor. Buffer amountCommitment, balanceCommitment; if (arg.amountCommitment) + { amountCommitment = *arg.amountCommitment; + } else + { amountCommitment = getPedersenCommitment(*arg.amt, blindingFactor); + } jv[sfAmountCommitment] = strHex(amountCommitment); auto const balanceBlindingFactor = generateBlindingFactor(); if (arg.balanceCommitment) + { balanceCommitment = *arg.balanceCommitment; + } else + { balanceCommitment = getPedersenCommitment(prevSenderSpending, balanceBlindingFactor); + } jv[sfBalanceCommitment] = strHex(balanceCommitment); if (arg.proof) + { jv[sfZKProof.jsonName] = *arg.proof; + } else { auto const ctxHash = @@ -1644,11 +1757,11 @@ MPTTester::sendJV( auto const issuerPubKey = getPubKey(issuer_); if (senderPubKey) - recipients.push_back({Slice(*senderPubKey), senderAmt}); + recipients.push_back({.publicKey = Slice(*senderPubKey), .encryptedAmount = senderAmt}); if (destPubKey) - recipients.push_back({Slice(*destPubKey), destAmt}); + recipients.push_back({.publicKey = Slice(*destPubKey), .encryptedAmount = destAmt}); if (issuerPubKey) - recipients.push_back({Slice(*issuerPubKey), issuerAmt}); + recipients.push_back({.publicKey = Slice(*issuerPubKey), .encryptedAmount = issuerAmt}); std::optional auditorPubKey; if (auditorAmt) @@ -1657,7 +1770,10 @@ MPTTester::sendJV( Throw("Auditor not registered"); auditorPubKey = getPubKey(*auditor_); if (auditorPubKey) - recipients.push_back({Slice(*auditorPubKey), *auditorAmt}); + { + recipients.push_back( + {.publicKey = Slice(*auditorPubKey), .encryptedAmount = *auditorAmt}); + } } std::optional proof; @@ -1671,17 +1787,24 @@ MPTTester::sendJV( recipients, blindingFactor, ctxHash, - {amountCommitment, *arg.amt, senderAmt, blindingFactor}, - {balanceCommitment, - prevSenderSpending, - *prevEncryptedSenderSpending, - balanceBlindingFactor}); + {.pedersenCommitment = amountCommitment, + .amt = *arg.amt, + .encryptedAmt = senderAmt, + .blindingFactor = blindingFactor}, + {.pedersenCommitment = balanceCommitment, + .amt = prevSenderSpending, + .encryptedAmt = *prevEncryptedSenderSpending, + .blindingFactor = balanceBlindingFactor}); } if (proof) + { jv[sfZKProof.jsonName] = strHex(*proof); + } else + { jv[sfZKProof.jsonName] = strHex(makeZeroBuffer(ecSendProofLength)); + } } return jv; @@ -1745,23 +1868,35 @@ MPTTester::confidentialClaw(MPTConfidentialClawback const& arg) jv[sfAccount] = account.human(); if (arg.holder) + { jv[sfHolder] = arg.holder->human(); + } else + { Throw("Holder not specified"); + } jv[jss::TransactionType] = jss::ConfidentialMPTClawback; if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else if (id_) + { jv[sfMPTokenIssuanceID] = to_string(*id_); + } else + { Throw("MPT has not been created"); + } if (arg.amt) jv[sfMPTAmount] = std::to_string(*arg.amt); if (arg.proof) + { jv[sfZKProof] = *arg.proof; + } else { auto const seq = arg.ticketSeq ? *arg.ticketSeq : env_.seq(account); @@ -1774,9 +1909,13 @@ MPTTester::confidentialClaw(MPTConfidentialClawback const& arg) auto const proof = getClawbackProof(*arg.holder, *arg.amt, *privKey, contextHash); if (proof) + { jv[sfZKProof] = strHex(*proof); + } else + { jv[sfZKProof] = strHex(makeZeroBuffer(ecClawbackProofLength)); + } } auto const holderPubAmt = getBalance(*arg.holder); @@ -1823,7 +1962,7 @@ MPTTester::generateKeyPair(Account const& account) { unsigned char privKey[ecPrivKeyLength]; secp256k1_pubkey pubKey; - if (!secp256k1_elgamal_generate_keypair(secp256k1Context(), privKey, &pubKey)) + if (secp256k1_elgamal_generate_keypair(secp256k1Context(), privKey, &pubKey) == 0) Throw("failed to generate key pair"); // Serialize public key to compressed format (33 bytes) @@ -1888,8 +2027,8 @@ MPTTester::decryptAmount(Account const& account, Buffer const& amt) const return std::nullopt; uint64_t decryptedAmt = 0; - if (!secp256k1_elgamal_decrypt( - secp256k1Context(), &decryptedAmt, &pair->c1, &pair->c2, privKey->data())) + if (secp256k1_elgamal_decrypt( + secp256k1Context(), &decryptedAmt, &pair->c1, &pair->c2, privKey->data()) == 0) { return std::nullopt; } @@ -1910,7 +2049,9 @@ MPTTester::getDecryptedBalance(Account const& account, EncryptedBalanceType bala Account decryptor = account; if (balanceType == ISSUER_ENCRYPTED_BALANCE) + { decryptor = issuer_; + } else if (balanceType == AUDITOR_ENCRYPTED_BALANCE) { if (!auditor_) @@ -1926,11 +2067,17 @@ MPTTester::mergeInboxJV(MPTMergeInbox const& arg) const { Json::Value jv; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -1946,11 +2093,17 @@ MPTTester::mergeInbox(MPTMergeInbox const& arg) { Json::Value jv; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -2025,13 +2178,19 @@ MPTTester::convertBack(MPTConvertBack const& arg) { Json::Value jv; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } jv[jss::TransactionType] = jss::ConfidentialMPTConvertBack; if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -2062,14 +2221,20 @@ MPTTester::convertBack(MPTConvertBack const& arg) Buffer pedersenCommitment; Buffer const pcBlindingFactor = generateBlindingFactor(); if (arg.pedersenCommitment) + { pedersenCommitment = *arg.pedersenCommitment; + } else + { pedersenCommitment = getPedersenCommitment(*prevSpendingBalance, pcBlindingFactor); + } jv[sfBalanceCommitment] = strHex(pedersenCommitment); if (arg.proof) + { jv[sfZKProof.jsonName] = strHex(*arg.proof); + } else { auto const version = getMPTokenVersion(*arg.account); @@ -2085,7 +2250,9 @@ MPTTester::convertBack(MPTConvertBack const& arg) // generate a dummy proof if no encrypted amount field, so that other // preflight/preclaim are checked if (!prevEncryptedSpendingBalance) + { proof = makeZeroBuffer(ecConvertBackProofLength); + } else { proof = getConvertBackProof( @@ -2166,13 +2333,19 @@ MPTTester::convertBackJV(MPTConvertBack const& arg, std::uint32_t seq) { Json::Value jv; if (arg.account) + { jv[sfAccount] = arg.account->human(); + } else + { Throw("Account not specified"); + } jv[jss::TransactionType] = jss::ConfidentialMPTConvertBack; if (arg.id) + { jv[sfMPTokenIssuanceID] = to_string(*arg.id); + } else { if (!id_) @@ -2200,14 +2373,20 @@ MPTTester::convertBackJV(MPTConvertBack const& arg, std::uint32_t seq) Buffer pedersenCommitment; Buffer const pcBlindingFactor = generateBlindingFactor(); if (arg.pedersenCommitment) + { pedersenCommitment = *arg.pedersenCommitment; + } else + { pedersenCommitment = getPedersenCommitment(*prevSpendingBalance, pcBlindingFactor); + } jv[sfBalanceCommitment] = strHex(pedersenCommitment); if (arg.proof) + { jv[sfZKProof.jsonName] = strHex(*arg.proof); + } else { auto const version = getMPTokenVersion(*arg.account); @@ -2216,8 +2395,11 @@ MPTTester::convertBackJV(MPTConvertBack const& arg, std::uint32_t seq) Buffer proof; if (!prevEncSpending) + { proof = makeZeroBuffer(ecConvertBackProofLength); + } else + { proof = getConvertBackProof( *arg.account, *arg.amt, @@ -2228,6 +2410,7 @@ MPTTester::convertBackJV(MPTConvertBack const& arg, std::uint32_t seq) .encryptedAmt = *prevEncSpending, .blindingFactor = pcBlindingFactor, }); + } jv[sfZKProof] = strHex(proof); } diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index 15e38f1b1a..78e5a2db56 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -582,7 +582,7 @@ public: std::uint32_t getMPTokenVersion(Account const account) const; - Buffer + static Buffer getPedersenCommitment(std::uint64_t const amount, Buffer const& pedersenBlindingFactor); friend BookSpec @@ -618,20 +618,30 @@ private: dstTag = arg.destinationTag; if (ticketSeq && delegateAcct) + { env_( jv, expectedFlags, expectedTer, ticket::use(*ticketSeq), delegate::as(*delegateAcct)); + } else if (ticketSeq) + { env_(jv, expectedFlags, expectedTer, ticket::use(*ticketSeq)); + } else if (delegateAcct) + { env_(jv, expectedFlags, expectedTer, delegate::as(*delegateAcct)); + } else if (dstTag) + { env_(jv, expectedFlags, expectedTer, dtag(*dstTag)); + } else + { env_(jv, expectedFlags, expectedTer); + } auto const err = env_.ter(); if (close_) env_.close();