1#include <test/jtx/ConfidentialTransfer.h>
3#include <test/jtx/Account.h>
4#include <test/jtx/Env.h>
5#include <test/jtx/mpt.h>
7#include <xrpl/basics/Buffer.h>
8#include <xrpl/basics/Slice.h>
9#include <xrpl/basics/base_uint.h>
10#include <xrpl/basics/contract.h>
11#include <xrpl/basics/strHex.h>
12#include <xrpl/protocol/ConfidentialTransfer.h>
13#include <xrpl/protocol/Protocol.h>
14#include <xrpl/protocol/TER.h>
15#include <xrpl/protocol/TxFlags.h>
17#include <utility/mpt_utility.h>
20#include <secp256k1_mpt.h>
43 mpt.create({.ownerCount = 1, .flags = flags});
45 for (
auto const& h : holders)
47 mpt.authorize({.account = h.account});
48 if ((flags & tfMPTRequireAuth) != 0)
49 mpt.authorize({.account = issuer, .holder = h.account});
50 mpt.pay(issuer, h.account, h.payAmount);
53 mpt.generateKeyPair(issuer);
54 for (
auto const& h : holders)
55 mpt.generateKeyPair(h.account);
57 mpt.generateKeyPair(requireOptionalRef(auditor,
"Missing auditor"));
61 .issuerPubKey = mpt.getPubKey(issuer),
62 .auditorPubKey = auditor ? mpt.getPubKey(requireOptionalRef(auditor,
"Missing auditor"))
63 : std::optional<Buffer>{},
66 for (
auto const& h : holders)
70 .amt = h.convertAmount,
71 .holderPubKey = mpt.getPubKey(h.account),
73 mpt.mergeInbox({.account = h.account});
77std::vector<test::jtx::Account>
83 for (
auto const& h : holders)
102 for (
auto const& holder : holders)
105 mpt.
pay(issuer, holder, 100);
110 for (
auto const& keyOwner : keyOwners)
127 .flags = tfMPTCanTransfer | tfMPTCanLock | tfMPTCanHoldConfidentialBalance,
134 mpt.
pay(alice, bob, bobAmt);
136 mpt.
pay(alice, carol, carolAmt);
200 ,
version(mpt.getMPTokenVersion(sender))
216 mpt.getDecryptedBalance(sender,
test::jtx::MPTTester::holderEncryptedSpending),
217 "Missing sender spending balance"))
219 mpt.getEncryptedBalance(sender,
test::jtx::MPTTester::holderEncryptedSpending),
220 "Missing sender encrypted spending balance"))
303 auto const spendingCt =
307 if (!spendingCt || !inboxCt)
310 auto const spendingAmt = mpt.
decryptAmount(currentKey, *spendingCt);
311 auto const inboxAmt = mpt.
decryptAmount(currentKey, *inboxCt);
312 if (!spendingAmt || !inboxAmt)
323 static Buffer const kBadCiphertext = []() {
332 return kBadCiphertext;
338 static Buffer const kTrivialCiphertext = []() {
351 return kTrivialCiphertext;
357 static Buffer const kTrivialCommitment = []() {
368 return kTrivialCommitment;
393 auto*
const ctx = mpt_secp256k1_context();
396 secp256k1_mpt_get_h_generator(ctx, &h);
401 unsigned char blindings[64];
402 std::memcpy(blindings, blindingFactors[0].data(), 32);
403 std::memcpy(blindings + 32, blindingFactors[1].data(), 32);
405 if (secp256k1_bulletproof_prove_agg(
406 ctx, proof.
data(), &proofLen, values.
data(), blindings, 2, &h, contextHash.
data()) == 0)
415 Buffer const& blindingFactor,
418 auto*
const ctx = mpt_secp256k1_context();
421 secp256k1_mpt_get_h_generator(ctx, &h);
426 if (secp256k1_bulletproof_prove_agg(
431 blindingFactor.
data(),
434 contextHash.
data()) == 0)
444 uint64_t claimedBalance,
445 uint64_t realBalance,
447 Buffer const& pedersenCommitment,
448 Buffer const& encryptedSpendingBalance,
449 Buffer const& pcBlindingFactor,
458 if (amt > realBalance)
461 auto*
const ctx = mpt_secp256k1_context();
465 secp256k1_pubkey pkHolder;
470 secp256k1_pubkey pcB;
475 secp256k1_pubkey b1, b2;
476 if (secp256k1_ec_pubkey_parse(
478 secp256k1_ec_pubkey_parse(
485 Buffer sigmaProof(SECP256K1_COMPACT_CONVERTBACK_PROOF_SIZE);
486 if (secp256k1_compact_convertback_prove(
490 holderPrivKey.data(),
491 pcBlindingFactor.
data(),
496 contextHash.
data()) != 1)
499 auto const forgedBulletproof =
505 proof.
data() + SECP256K1_COMPACT_CONVERTBACK_PROOF_SIZE,
506 forgedBulletproof.data(),
520 auto*
const ctx = mpt_secp256k1_context();
529 secp256k1_ec_pubkey_parse(
532 if (secp256k1_ec_pubkey_parse(
538 if (secp256k1_ec_pubkey_parse(
543 secp256k1_pubkey pkSender, pcAmount, pcBalance, b1, b2;
544 if (secp256k1_ec_pubkey_parse(
546 secp256k1_ec_pubkey_parse(
548 secp256k1_ec_pubkey_parse(
550 secp256k1_ec_pubkey_parse(
552 secp256k1_ec_pubkey_parse(
563 Buffer sigmaProof(SECP256K1_COMPACT_STANDARD_PROOF_SIZE);
564 if (secp256k1_compact_standard_prove(
570 senderPrivKey.
data(),
581 ctxHash.data()) != 1)
596 secp256k1_mpt_scalar_add(
603 std::memcpy(combinedProof.data(), sigmaProof.
data(), SECP256K1_COMPACT_STANDARD_PROOF_SIZE);
605 combinedProof.data() + SECP256K1_COMPACT_STANDARD_PROOF_SIZE,
606 forgedBulletproof.data(),
609 return combinedProof;
Like std::vector<char> but better.
std::size_t size() const noexcept
Returns the number of bytes in the buffer.
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
static Buffer getForgedSingleBulletproof(uint64_t value, Buffer const &blindingFactor, UInt256 const &contextHash)
static Buffer getForgedSendProof(test::jtx::MPTTester &mpt, test::jtx::Env &env, test::jtx::Account const &sender, test::jtx::Account const &dest, ConfidentialSendSetup const &setup)
static std::optional< std::pair< Buffer, Buffer > > reencryptHolderBalances(test::jtx::MPTTester &mpt, test::jtx::Account const &holder, test::jtx::Account const ¤tKey, test::jtx::Account const &newKey)
static void setupConfidentialIssuance(test::jtx::MPTTester &mpt, test::jtx::Account const &issuer, std::vector< test::jtx::Account > const &holders, std::vector< test::jtx::Account > const &keyOwners={}, std::uint32_t flags=tfMPTCanTransfer|tfMPTCanHoldConfidentialBalance)
static T requireOptional(std::optional< T > value, char const *message)
static Buffer const & getBadCiphertext()
static void setupBatchEnv(test::jtx::MPTTester &mpt, test::jtx::Account const &alice, test::jtx::Account const &bob, test::jtx::Account const &carol, test::jtx::Account const &dave, std::uint64_t bobAmt, std::uint64_t carolAmt)
static T const & requireOptionalRef(std::optional< T > const &value, char const *message)
static Buffer getForgedBulletproof(std::array< uint64_t, 2 > const &values, std::array< Buffer, 2 > const &blindingFactors, UInt256 const &contextHash)
static std::string getTrivialSendProofHex()
static Buffer getForgedConvertBackProof(test::jtx::MPTTester &mpt, test::jtx::Account const &holder, uint64_t claimedBalance, uint64_t realBalance, uint64_t amt, Buffer const &pedersenCommitment, Buffer const &encryptedSpendingBalance, Buffer const &pcBlindingFactor, UInt256 const &contextHash)
static Buffer const & getTrivialCommitment()
static Buffer const & getTrivialCiphertext()
An immutable linear range of bytes.
Immutable cryptographic account descriptor.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Test helper for creating, mutating, and asserting MPT and confidential MPT ledger state.
static constexpr auto holderEncryptedInbox
Buffer encryptAmount(Account const &account, uint64_t const amt, Buffer const &blindingFactor) const
void mergeInbox(MPTMergeInbox const &arg=MPTMergeInbox{}, std::source_location const &loc=std::source_location::current())
std::optional< Buffer > getEncryptedBalance(Account const &account, EncryptedBalanceType option=holderEncryptedInbox) const
std::uint32_t generateKeyPair(Account const &account)
MPTID const & issuanceID() const
static constexpr auto holderEncryptedSpending
std::optional< uint64_t > decryptAmount(Account const &account, Buffer const &amt, std::optional< std::uint32_t > epoch=std::nullopt) const
std::optional< Buffer > getConfidentialSendProof(Account const &sender, std::uint64_t const amount, std::vector< ConfidentialRecipient > const &recipients, Slice const &blindingFactor, UInt256 const &contextHash, PedersenProofParams const &amountParams, PedersenProofParams const &balanceParams) const
std::optional< Buffer > getPubKey(Account const &account, std::optional< std::uint32_t > epoch=std::nullopt) const
void pay(Account const &src, Account const &dest, std::int64_t amount, std::optional< TER > err=std::nullopt, std::optional< std::vector< std::string > > credentials=std::nullopt, std::source_location const &loc=std::source_location::current())
void create(MPTCreate const &arg=MPTCreate{}, std::source_location const &loc=std::source_location::current())
void set(MPTSet const &set={}, std::source_location const &loc=std::source_location::current())
void authorize(MPTAuthorize const &arg=MPTAuthorize{}, std::source_location const &loc=std::source_location::current())
void convert(MPTConvert const &arg=MPTConvert{}, std::source_location const &loc=std::source_location::current())
std::optional< Buffer > getPrivKey(Account const &account, std::optional< std::uint32_t > epoch=std::nullopt) const
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint8_t kEcCompressedPrefixEvenY
Compressed EC point prefix for even y-coordinate.
constexpr std::size_t kEcBlindingFactorLength
Length of the EC blinding factor in bytes.
constexpr std::size_t kCompressedEcPointLength
Length of EC point (compressed).
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::string strHex(FwdIt begin, FwdIt end)
UInt256 getSendContextHash(AccountID const &account, UInt192 const &issuanceID, std::uint32_t sequence, AccountID const &destination, std::uint32_t version)
Generates the context hash for ConfidentialMPTSend transactions.
std::optional< Buffer > encryptAmount(uint64_t const amt, Slice const &pubKeySlice, Slice const &blindingFactor)
Encrypts an amount using ElGamal encryption.
constexpr std::size_t kEcGamalEncryptedTotalLength
EC ElGamal ciphertext length: two compressed EC points concatenated.
constexpr std::size_t kEcConvertBackProofLength
128 bytes compact sigma proof + 688 bytes single bulletproof.
constexpr std::size_t kEcSingleBulletproofLength
Length of single bulletproof (range proof for 1 commitment) in bytes.
constexpr std::size_t kEcPedersenCommitmentLength
Length of Pedersen Commitment (compressed).
constexpr std::size_t kEcCiphertextComponentLength
Length of one compressed EC point component in an EC ElGamal ciphertext.
constexpr std::size_t kEcDoubleBulletproofLength
Length of double bulletproof (range proof for 2 commitments) in bytes.
Buffer generateBlindingFactor()
Generates a cryptographically secure blinding factor (size=xrpl::kEcBlindingFactorLength).
constexpr std::size_t kEcSendProofLength
192 bytes compact sigma proof + 754 bytes double bulletproof.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
static std::vector< test::jtx::Account > extractAccounts(std::vector< HolderInit > const &holders)
ConfidentialEnv(test::jtx::Env &env, test::jtx::Account const &issuer, std::vector< HolderInit > const &holders, std::uint32_t flags=tfMPTCanLock|tfMPTCanHoldConfidentialBalance|tfMPTCanTransfer, std::optional< test::jtx::Account > auditor=std::nullopt)
Buffer amountBlindingFactor
std::optional< Buffer > generateProof(test::jtx::MPTTester &mpt, test::jtx::Env &env, test::jtx::Account const &sender, test::jtx::Account const &dest) const
std::optional< Buffer > auditorPubKey
std::vector< ConfidentialRecipient > recipients
test::jtx::MPTConfidentialSend sendArgs(test::jtx::Account const &sender, test::jtx::Account const &dest, Buffer const &proof, std::optional< TER > err=std::nullopt) const
Buffer prevEncryptedSpending
ConfidentialSendSetup(test::jtx::MPTTester &mpt, test::jtx::Account const &sender, test::jtx::Account const &dest, test::jtx::Account const &issuer, uint64_t amount, std::optional< std::reference_wrapper< test::jtx::Account const > > auditor=std::nullopt)
std::optional< Buffer > auditorAmt
Buffer balanceBlindingFactor
Arguments for building a ConfidentialMPTSend test transaction.