fix clang-tidy

This commit is contained in:
yinyiqian1
2026-04-23 01:19:27 -04:00
parent c53d6aca08
commit b0386622ca
12 changed files with 359 additions and 62 deletions

View File

@@ -1,11 +1,29 @@
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/basics/Buffer.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <openssl/rand.h>
#include <utility/mpt_utility.h>
#include <secp256k1.h>
#include <secp256k1_mpt.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
#include <stdexcept>
#include <vector>
namespace xrpl {
/**

View File

@@ -1,7 +1,9 @@
#include <xrpl/tx/invariants/MPTInvariant.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>

View File

@@ -1,12 +1,19 @@
#include <xrpl/tx/transactors/token/ConfidentialMPTClawback.h>
#include <xrpl/ledger/View.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/Transactor.h>
#include <memory>
#include <utility>
namespace xrpl {

View File

@@ -1,13 +1,21 @@
#include <xrpl/tx/transactors/token/ConfidentialMPTConvert.h>
#include <xrpl/ledger/View.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/Transactor.h>
#include <memory>
#include <optional>
#include <utility>
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))
{

View File

@@ -1,15 +1,22 @@
#include <xrpl/tx/transactors/token/ConfidentialMPTConvertBack.h>
#include <xrpl/ledger/View.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/Transactor.h>
#include <cstddef>
#include <memory>
#include <optional>
#include <utility>
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))
{

View File

@@ -1,13 +1,20 @@
#include <xrpl/tx/transactors/token/ConfidentialMPTMergeInbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/Transactor.h>
#include <memory>
#include <utility>
namespace xrpl {

View File

@@ -1,14 +1,21 @@
#include <xrpl/tx/transactors/token/ConfidentialMPTSend.h>
#include <xrpl/ledger/View.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/Transactor.h>
#include <memory>
#include <optional>
#include <utility>
namespace xrpl {
@@ -86,9 +93,12 @@ verifySendProofs(
std::optional<ConfidentialRecipient> 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],

View File

@@ -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

View File

@@ -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

View File

@@ -1,12 +1,44 @@
#include <test/jtx.h>
#include <test/jtx/Account.h>
#include <test/jtx/Env.h>
#include <test/jtx/TestHelpers.h>
#include <test/jtx/amount.h>
#include <test/jtx/batch.h>
#include <test/jtx/credentials.h>
#include <test/jtx/delegate.h>
#include <test/jtx/deposit.h>
#include <test/jtx/flags.h>
#include <test/jtx/mpt.h>
#include <test/jtx/pay.h>
#include <test/jtx/ter.h>
#include <test/jtx/ticket.h>
#include <test/jtx/trust.h>
#include <test/jtx/vault.h>
#include <xrpl/basics/Buffer.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/json/json_value.h>
#include <xrpl/ledger/OpenView.h>
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/jss.h>
#include <openssl/rand.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <initializer_list>
#include <memory>
#include <string>
#include <utility>
#include <vector>
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,

View File

@@ -5,12 +5,13 @@
#include <test/jtx/Env.h>
#include <test/jtx/amount.h>
#include <test/jtx/credentials.h>
#include <test/jtx/mpt.h>
#include <test/jtx/owners.h>
#include <test/jtx/pay.h>
#include <test/jtx/ter.h>
#include <test/jtx/trust.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/StringUtilities.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/strHex.h>
@@ -32,9 +33,15 @@
#include <utility/mpt_utility.h>
#include <secp256k1.h>
#include <secp256k1_mpt.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <functional>
#include <iostream>
#include <optional>
#include <stdexcept>
#include <string>
@@ -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<Account> 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<std::runtime_error>(
"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<std::runtime_error>(
"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<std::runtime_error>("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<std::runtime_error>(
"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<std::runtime_error>("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<std::runtime_error>("Account not specified");
}
if (arg.dest)
{
jv[sfDestination] = arg.dest->human();
}
else
{
Throw<std::runtime_error>("Destination not specified");
}
if (!arg.amt)
Throw<std::runtime_error>("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<Buffer> 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<Buffer> 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<std::runtime_error>("Account not specified");
}
if (arg.dest)
{
jv[sfDestination] = arg.dest->human();
}
else
{
Throw<std::runtime_error>("Destination not specified");
}
if (!arg.amt)
Throw<std::runtime_error>("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<Buffer> 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<Buffer> auditorPubKey;
if (auditorAmt)
@@ -1657,7 +1770,10 @@ MPTTester::sendJV(
Throw<std::runtime_error>("Auditor not registered");
auditorPubKey = getPubKey(*auditor_);
if (auditorPubKey)
recipients.push_back({Slice(*auditorPubKey), *auditorAmt});
{
recipients.push_back(
{.publicKey = Slice(*auditorPubKey), .encryptedAmount = *auditorAmt});
}
}
std::optional<Buffer> 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<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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<std::runtime_error>("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);
}

View File

@@ -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();