Compare commits

..

26 Commits

Author SHA1 Message Date
Bart
b6a09a4d2c release: Bump version to 3.2.0-b3 2026-04-01 13:27:58 -04:00
Valentin Balaschenko
3adad49c86 fix: Remove fatal assertion on Linux thread name truncation (#6690) 2026-04-01 13:27:23 -04:00
Alex Kremer
f04943fc50 chore: Enable clang-tidy coreguidelines checks (#6698)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-04-01 13:27:23 -04:00
Ayaz Salikhov
ab7f683b2f ci: Allow uploading artifacts for XRPLF org (#6702) 2026-04-01 13:27:23 -04:00
Vito Tumas
14749fdfb0 fix: Enforce aggregate MaximumAmount in multi-send MPT (#6644)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-04-01 13:27:22 -04:00
Ayaz Salikhov
c6ddf6aa1c chore: Use nudb recipe from the upstream (#6701) 2026-04-01 13:27:22 -04:00
Mayukha Vadari
ee3a08c8d4 fix: Fix previous ledger size typo in RCLConsensus (#6696) 2026-04-01 13:27:22 -04:00
Alex Kremer
2dc705bd99 chore: Enable clang-tidy misc checks (#6655) 2026-04-01 13:27:22 -04:00
Ayaz Salikhov
7315c57edc ci: Use pull_request_target to check for signed commits (#6697) 2026-04-01 13:27:22 -04:00
Bart
5a66086fce chore: Remove unnecessary clang-format off/on directives (#6682)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-04-01 13:27:21 -04:00
Pratik Mankawde
682dda8bfc fix: Fix Workers::stop() race between m_allPaused and m_runningTaskCount (#6574)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 13:27:21 -04:00
Bart
aac17f588a release: Bump version to 3.2.0-b2 2026-03-30 14:52:51 -04:00
Ayaz Salikhov
cbc09b2999 ci: Only publish docs in public repos (#6687) 2026-03-30 14:52:09 -04:00
Alex Kremer
453d94da17 chore: Enable remaining clang-tidy performance checks (#6648)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-30 14:52:09 -04:00
Jingchen
b36aedb4d5 refactor: Address PR comments after the modularisation PRs (#6389)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-03-30 14:52:09 -04:00
Alex Kremer
18540c97a5 chore: Fix clang-tidy header filter (#6686) 2026-03-30 14:52:08 -04:00
dependabot[bot]
8e3d87fce3 ci: [DEPENDABOT] bump actions/deploy-pages from 4.0.5 to 5.0.0 (#6684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 14:52:08 -04:00
dependabot[bot]
b83dc9aa16 ci: [DEPENDABOT] bump codecov/codecov-action from 5.5.3 to 6.0.0 (#6685)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 14:52:08 -04:00
Pratik Mankawde
0c76bf991a fix: Guard Coro::resume() against completed coroutines (#6608)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 14:52:08 -04:00
Vito Tumas
29aba28f5b refactor: Split LoanInvariant into LoanBrokerInvariant and LoanInvariant (#6674) 2026-03-30 14:52:08 -04:00
Ayaz Salikhov
b3f14c4052 ci: Don't publish docs on release branches (#6673) 2026-03-30 14:52:08 -04:00
Jingchen
e26624dcd1 refactor: Make function naming in ServiceRegistry consistent (#6390)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Ed Hennis <ed@ripple.com>
2026-03-30 14:52:08 -04:00
Valentin Balaschenko
885f7b8c33 chore: Shorten job names to stay within Linux 15-char thread limit (#6669) 2026-03-30 14:52:07 -04:00
Vito Tumas
dcf973bc50 fix: Improve loan invariant message (#6668) 2026-03-30 14:52:07 -04:00
Ayaz Salikhov
68596f60d8 ci: Upload artifacts only in public repositories (#6670) 2026-03-30 14:52:07 -04:00
Bart
aac64d3b85 Update version (#6672) 2026-03-26 09:50:04 -04:00
235 changed files with 884 additions and 19406 deletions

View File

@@ -76,11 +76,11 @@ fi
if ! grep -q 'Dev Null' src/test/rpc/ValidatorInfo_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp
fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/server_info/Manifest.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" > src/xrpld/rpc/handlers/server_info/Manifest.cpp
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/DoManifest.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/DoManifest.cpp)" > src/xrpld/rpc/handlers/DoManifest.cpp
fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/ValidatorInfo.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/ValidatorInfo.cpp
fi
if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb

View File

@@ -10,4 +10,4 @@ permissions:
jobs:
check_commits:
uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@e2c7f400d1e85ae65dad552fd425169fbacca4a3
uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@481048b78b94ac3343d1292b4ef125a813879f2b

View File

@@ -11,4 +11,4 @@ on:
jobs:
check_title:
if: ${{ github.event.pull_request.draft != true }}
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@a5d8dd35be543365e90a11358447130c8763871d
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@e2c7f400d1e85ae65dad552fd425169fbacca4a3

View File

@@ -14,7 +14,7 @@ on:
jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@9307df762265e15c745ddcdb38a581c989f7f349
uses: XRPLF/actions/.github/workflows/pre-commit.yml@e7896f15cc60d0da1a272c77ee5c4026b424f9c7
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'

View File

@@ -47,7 +47,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
with:
enable_ccache: false

View File

@@ -107,7 +107,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
with:
enable_ccache: ${{ inputs.ccache_enabled }}

View File

@@ -35,7 +35,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
with:
enable_ccache: false

View File

@@ -70,7 +70,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
with:
enable_ccache: false

View File

@@ -38,8 +38,6 @@ This section contains changes targeting a future version.
### Bugfixes
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
- `ping`: The `ip` field is no longer returned as an empty string for proxied connections without a forwarded-for header. It is now omitted, consistent with the behavior for identified connections. [#6730](https://github.com/XRPLF/rippled/pull/6730)
- gRPC `GetLedgerDiff`: Fixed error message that incorrectly said "base ledger not validated" when the desired ledger was not validated. [#6730](https://github.com/XRPLF/rippled/pull/6730)
## XRP Ledger server version 3.1.0

View File

@@ -88,7 +88,6 @@ find_package(ed25519 REQUIRED)
find_package(gRPC REQUIRED)
find_package(LibArchive REQUIRED)
find_package(lz4 REQUIRED)
find_package(mpt-crypto REQUIRED)
find_package(nudb REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(secp256k1 REQUIRED)
@@ -101,7 +100,6 @@ target_link_libraries(
INTERFACE
ed25519::ed25519
lz4::lz4
mpt-crypto::mpt-crypto
OpenSSL::Crypto
OpenSSL::SSL
secp256k1::secp256k1

View File

@@ -12,7 +12,6 @@
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"openssl/3.6.1#e6399de266349245a4542fc5f6c71552%1774458290.139",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1774883011.384",
"mpt-crypto/0.2.0-rc1#ed3f241f69d8b9ebf80069d1923d93a8%1773853481.755",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
@@ -35,7 +34,6 @@
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
@@ -60,12 +58,6 @@
],
"lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
],
"openssl/3.5.5": [
"openssl/3.6.1"
],
"openssl/[>=3 <4]": [
"openssl/3.6.1"
]
},
"config_requires": []

View File

@@ -31,7 +31,6 @@ class Xrpl(ConanFile):
"ed25519/2015.03",
"grpc/1.78.1",
"libarchive/3.8.1",
"mpt-crypto/0.2.0-rc1",
"nudb/2.0.9",
"openssl/3.6.1",
"secp256k1/0.7.1",
@@ -215,7 +214,6 @@ class Xrpl(ConanFile):
"grpc::grpc++",
"libarchive::libarchive",
"lz4::lz4",
"mpt-crypto::mpt-crypto",
"nudb::nudb",
"openssl::crypto",
"protobuf::libprotobuf",

View File

@@ -55,7 +55,6 @@ words:
- autobridging
- bimap
- bindir
- blindings
- bookdir
- Bougalis
- Britto
@@ -88,7 +87,6 @@ words:
- daria
- dcmake
- dearmor
- decryptor
- deleteme
- demultiplexer
- deserializaton
@@ -98,7 +96,6 @@ words:
- distro
- doxyfile
- dxrpl
- elgamal
- endmacro
- exceptioned
- Falco
@@ -108,7 +105,6 @@ words:
- fmtdur
- fsanitize
- funclets
- Gamal
- gcov
- gcovr
- ghead
@@ -195,7 +191,6 @@ words:
- partitioner
- paychan
- paychans
- Pedersen
- permdex
- perminute
- permissioned
@@ -232,7 +227,6 @@ words:
- sahyadri
- Satoshi
- scons
- Schnorr
- secp
- sendq
- seqit
@@ -260,7 +254,6 @@ words:
- stvar
- stvector
- stxchainattestations
- summands
- superpeer
- superpeers
- takergets

View File

@@ -28,7 +28,7 @@ inline constexpr struct open_ledger_t
/** Batch view construction tag.
Views constructed with this tag are part of a stack of views
used during batch transaction application.
used during batch transaction applied.
*/
inline constexpr struct batch_view_t
{

View File

@@ -157,11 +157,4 @@ rippleUnlockEscrowMPT(
STAmount const& grossAmount,
beast::Journal j);
TER
createMPToken(
ApplyView& view,
MPTID const& mptIssuanceID,
AccountID const& account,
std::uint32_t const flags);
} // namespace xrpl

View File

@@ -1,5 +1,3 @@
#pragma once
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/STVector256.h>
#include <xrpl/protocol/Serializer.h>

View File

@@ -1,460 +0,0 @@
#pragma once
#include <xrpl/basics/Slice.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/detail/secp256k1.h>
#include <secp256k1_mpt.h>
namespace xrpl {
/**
* @brief Bundles an ElGamal public key with its associated encrypted amount.
*
* Used to represent a recipient in confidential transfers, containing both
* the recipient's ElGamal public key and the ciphertext encrypting the
* transfer amount under that key.
*/
struct ConfidentialRecipient
{
Slice publicKey; ///< The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
Slice encryptedAmount; ///< The encrypted amount ciphertext
///< (size=xrpl::ecGamalEncryptedTotalLength).
};
/// Holds two secp256k1 public key components representing an ElGamal ciphertext (C1, C2).
struct EcPair
{
secp256k1_pubkey c1;
secp256k1_pubkey c2;
};
/**
* @brief Increments the confidential balance version counter on an MPToken.
*
* The version counter is used to prevent replay attacks by binding proofs
* to a specific state of the account's confidential balance. Wraps to 0
* on overflow (defined behavior for unsigned integers).
*
* @param mptoken The MPToken ledger entry to update.
*/
inline void
incrementConfidentialVersion(STObject& mptoken)
{
// 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;
}
/**
* @brief Generates the context hash for ConfidentialMPTSend transactions.
*
* Creates a unique 256-bit hash that binds the zero-knowledge proofs to
* this specific send transaction, preventing proof reuse across transactions.
*
* @param account The sender's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or ticket number.
* @param destination The destination account ID.
* @param version The sender's confidential balance version.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getSendContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
AccountID const& destination,
std::uint32_t version);
/**
* @brief Generates the context hash for ConfidentialMPTClawback transactions.
*
* Creates a unique 256-bit hash that binds the equality proof to this
* specific clawback transaction.
*
* @param account The issuer's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or ticket number.
* @param holder The holder's account ID being clawed back from.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getClawbackContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
AccountID const& holder);
/**
* @brief Generates the context hash for ConfidentialMPTConvert transactions.
*
* Creates a unique 256-bit hash that binds the Schnorr proof (for key
* registration) to this specific convert transaction.
*
* @param account The holder's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or a ticket number.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getConvertContextHash(AccountID const& account, uint192 const& issuanceID, std::uint32_t sequence);
/**
* @brief Generates the context hash for ConfidentialMPTConvertBack transactions.
*
* Creates a unique 256-bit hash that binds the zero-knowledge proofs to
* this specific convert-back transaction.
*
* @param account The holder's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or a ticket number.
* @param version The holder's confidential balance version.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getConvertBackContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
std::uint32_t version);
/**
* @brief Parses an ElGamal ciphertext into two secp256k1 public key components.
*
* Breaks a 66-byte encrypted amount (two 33-byte compressed EC points) into
* a pair containing (C1, C2) for use in cryptographic operations.
*
* @param buffer The 66-byte buffer containing the compressed ciphertext.
* @return The parsed pair (c1, c2) if successful, std::nullopt if the buffer is invalid.
*/
std::optional<EcPair>
makeEcPair(Slice const& buffer);
/**
* @brief Serializes an EcPair into compressed form.
*
* Converts an EcPair (C1, C2) back into a 66-byte buffer containing
* two 33-byte compressed EC points.
*
* @param pair The EcPair to serialize.
* @return The 66-byte buffer, or std::nullopt if serialization fails.
*/
std::optional<Buffer>
serializeEcPair(EcPair const& pair);
/**
* @brief Verifies that a buffer contains two valid, parsable EC public keys.
*
* @param buffer The input buffer containing two concatenated components.
* @return true if both components can be parsed successfully, false otherwise.
*/
bool
isValidCiphertext(Slice const& buffer);
/**
* @brief Verifies that a buffer contains a valid, parsable compressed EC point.
*
* Can be used to validate both compressed public keys and Pedersen commitments.
* Fails early if the prefix byte is not 0x02 or 0x03.
*
* @param buffer The input buffer containing a compressed EC point (33 bytes).
* @return true if the point can be parsed successfully, false otherwise.
*/
bool
isValidCompressedECPoint(Slice const& buffer);
/**
* @brief Homomorphically adds two ElGamal ciphertexts.
*
* Uses the additive homomorphic property of ElGamal encryption to compute
* Enc(a + b) from Enc(a) and Enc(b) without decryption.
*
* @param a The first ciphertext (66 bytes).
* @param b The second ciphertext (66 bytes).
* @return The resulting ciphertext Enc(a + b), or std::nullopt on failure.
*/
std::optional<Buffer>
homomorphicAdd(Slice const& a, Slice const& b);
/**
* @brief Homomorphically subtracts two ElGamal ciphertexts.
*
* Uses the additive homomorphic property of ElGamal encryption to compute
* Enc(a - b) from Enc(a) and Enc(b) without decryption.
*
* @param a The minuend ciphertext (66 bytes).
* @param b The subtrahend ciphertext (66 bytes).
* @return The resulting ciphertext Enc(a - b), or std::nullopt on failure.
*/
std::optional<Buffer>
homomorphicSubtract(Slice const& a, Slice const& b);
/**
* @brief Encrypts an amount using ElGamal encryption.
*
* Produces a ciphertext C = (C1, C2) where C1 = r*G and C2 = m*G + r*Pk,
* using the provided blinding factor r.
*
* @param amt The plaintext amount to encrypt.
* @param pubKeySlice The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param blindingFactor The randomness used as blinding factor r
* (size=xrpl::ecBlindingFactorLength).
* @return The ciphertext (size=xrpl::ecGamalEncryptedTotalLength), or std::nullopt on failure.
*/
std::optional<Buffer>
encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindingFactor);
/**
* @brief Generates the canonical zero encryption for a specific MPToken.
*
* Creates a deterministic encryption of zero that is unique to the account
* and MPT issuance. Used to initialize confidential balance fields.
*
* @param pubKeySlice The holder's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param account The account ID of the token holder.
* @param mptId The MPToken Issuance ID.
* @return The canonical zero ciphertext (size=xrpl::ecGamalEncryptedTotalLength), or std::nullopt
* on failure.
*/
std::optional<Buffer>
encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, MPTID const& mptId);
/**
* @brief Verifies a Schnorr proof of knowledge of an ElGamal private key.
*
* Proves that the submitter knows the secret key corresponding to the
* provided public key, without revealing the secret key itself.
*
* @param pubKeySlice The ElGamal public key (size=xrpl::ecPubKeyLength).
* @param proofSlice The Schnorr proof (size=xrpl::ecSchnorrProofLength).
* @param contextHash The 256-bit context hash binding the proof.
* @return tesSUCCESS if valid, or an error code otherwise.
*/
TER
verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 const& contextHash);
/**
* @brief Validates the format of encrypted amount fields in a transaction.
*
* Checks that all ciphertext fields in the transaction object have the
* correct length and contain valid EC points. This function is only used
* by ConfidentialMPTConvert and ConfidentialMPTConvertBack transactions.
*
* @param object The transaction object containing encrypted amount fields.
* @return tesSUCCESS if all formats are valid, temMALFORMED if required fields
* are missing, or temBAD_CIPHERTEXT if format validation fails.
*/
NotTEC
checkEncryptedAmountFormat(STObject const& object);
/**
* @brief Verifies revealed amount encryptions for all recipients.
*
* Validates that the same amount was correctly encrypted for the holder,
* issuer, and optionally the auditor using their respective public keys.
*
* @param amount The revealed plaintext amount.
* @param blindingFactor The blinding factor used in all encryptions
* (size=xrpl::ecBlindingFactorLength).
* @param holder The holder's public key and encrypted amount.
* @param issuer The issuer's public key and encrypted amount.
* @param auditor Optional auditor's public key and encrypted amount.
* @return tesSUCCESS if all encryptions are valid, or an error code otherwise.
*/
TER
verifyRevealedAmount(
uint64_t const amount,
Slice const& blindingFactor,
ConfidentialRecipient const& holder,
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor);
/**
* @brief Returns the number of recipients in a confidential transfer.
*
* Returns 4 if an auditor is present (sender, destination, issuer, auditor),
* or 3 if no auditor (sender, destination, issuer).
*
* @param hasAuditor Whether the issuance has an auditor configured.
* @return The number of recipients (3 or 4).
*/
constexpr std::size_t
getConfidentialRecipientCount(bool hasAuditor)
{
return hasAuditor ? 4 : 3;
}
/**
* @brief Returns the size of a multi-ciphertext equality proof.
*
* Computes the byte size required for a zero-knowledge proof that demonstrates
* multiple ciphertexts encrypt the same plaintext value. The size depends on
* the number of recipients.
*
* @param nRecipients The number of recipients (typically 3 or 4).
* @return The proof size in bytes.
*/
inline std::size_t
getEqualityProofSize(std::size_t nRecipients)
{
return secp256k1_mpt_proof_equality_shared_r_size(nRecipients);
}
/**
* @brief Verifies a clawback equality proof.
*
* Proves that the issuer knows the exact amount encrypted in the holder's
* balance ciphertext. Used in ConfidentialMPTClawback to verify the issuer
* can decrypt the balance using their private key.
*
* @param amount The revealed plaintext amount.
* @param proof The zero-knowledge proof bytes.
* @param pubKeySlice The issuer's ElGamal public key (64 bytes).
* @param ciphertext The issuer's encrypted balance on the holder's account (66 bytes).
* @param contextHash The 256-bit context hash binding the proof.
* @return tesSUCCESS if the proof is valid, or an error code otherwise.
*/
TER
verifyClawbackEqualityProof(
uint64_t const amount,
Slice const& proof,
Slice const& pubKeySlice,
Slice const& ciphertext,
uint256 const& contextHash);
/**
* @brief Generates a cryptographically secure 32-byte blinding factor.
*
* Produces random bytes suitable for use as an ElGamal blinding factor
* or Pedersen commitment randomness.
*
* @return A 32-byte buffer containing the random blinding factor.
*/
Buffer
generateBlindingFactor();
/**
* @brief Verifies all zero-knowledge proofs for a ConfidentialMPTSend transaction.
*
* This function calls mpt_verify_send_proof API in the mpt-crypto utility lib, which verifies the
* equality proof, amount linkage, balance linkage, and range proof.
* Equality proof: Proves the same value is encrypted for the sender, receiver, issuer, and auditor.
* Amount linkage: Proves the send amount matches the amount Pedersen commitment.
* Balance linkage: Proves the sender's balance matches the balance Pedersen
* commitment.
* Range proof: Proves the amount and the remaining balance are within range [0, 2^64-1].
*
* @param proof The full proof blob.
* @param sender The sender's public key and encrypted amount.
* @param destination The destination's public key and encrypted amount.
* @param issuer The issuer's public key and encrypted amount.
* @param auditor The auditor's public key and encrypted amount if present.
* @param spendingBalance The sender's current spending balance ciphertext.
* @param amountCommitment The Pedersen commitment to the send amount.
* @param balanceCommitment The Pedersen commitment to the sender's balance.
* @param contextHash The context hash binding the proof.
* @return tesSUCCESS if all proofs are valid, or an error code otherwise.
*/
TER
verifySendProof(
Slice const& proof,
ConfidentialRecipient const& sender,
ConfidentialRecipient const& destination,
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor,
Slice const& spendingBalance,
Slice const& amountCommitment,
Slice const& balanceCommitment,
uint256 const& contextHash);
/**
* @brief Verifies all zero-knowledge proofs for a ConfidentialMPTConvertBack transaction.
*
* This function calls mpt_verify_convert_back_proof API in the mpt-crypto utility lib, which
* verifies the balance linkage proof and range proof. Balance linkage proof: proves the balance
* commitment matches the spending ciphertext. Range proof: proves the remaining balance after
* convert back is within range [0, 2^64-1].
*
* @param proof The full proof blob.
* @param pubKeySlice The holder's public key.
* @param spendingBalance The holder's spending balance ciphertext.
* @param balanceCommitment The Pedersen commitment to the balance.
* @param amount The amount being converted back to public.
* @param contextHash The context hash binding the proof.
* @return tesSUCCESS if all proofs are valid, or an error code otherwise.
*/
TER
verifyConvertBackProof(
Slice const& proof,
Slice const& pubKeySlice,
Slice const& spendingBalance,
Slice const& balanceCommitment,
uint64_t amount,
uint256 const& contextHash);
/**
* @brief Sequential reader for extracting proof components from a ZKProof blob.
*
* Encapsulates the offset-based arithmetic for slicing a concatenated proof
* blob into its individual components (equality proofs, Pedersen linkage
* proofs, bulletproofs, etc.). Performs bounds checking on every read and
* tracks whether the entire blob has been consumed.
*
* Usage:
* @code
* ProofReader reader(tx[sfZKProof]);
* auto equalityProof = reader.read(sizeEquality);
* auto pedersenProof = reader.read(ecPedersenProofLength);
* if (!equalityProof || !pedersenProof || !reader.done())
* return tecINTERNAL;
* @endcode
*/
class ProofReader
{
Slice data_;
std::size_t offset_ = 0;
public:
explicit ProofReader(Slice data) : data_(data)
{
}
/**
* @brief Read the next @p length bytes from the proof blob.
*
* @param length Number of bytes to read.
* @return A Slice of the requested bytes, or std::nullopt if there are
* not enough remaining bytes.
*/
[[nodiscard]] std::optional<Slice>
read(std::size_t length)
{
if (offset_ + length > data_.size())
return std::nullopt;
auto result = data_.substr(offset_, length);
offset_ += length;
return result;
}
/**
* @brief Returns true when every byte has been consumed.
*/
[[nodiscard]] bool
done() const
{
return offset_ == data_.size();
}
};
} // namespace xrpl

View File

@@ -173,8 +173,7 @@ enum LedgerEntryType : std::uint16_t {
LSF_FLAG(lsfMPTCanEscrow, 0x00000008) \
LSF_FLAG(lsfMPTCanTrade, 0x00000010) \
LSF_FLAG(lsfMPTCanTransfer, 0x00000020) \
LSF_FLAG(lsfMPTCanClawback, 0x00000040) \
LSF_FLAG(lsfMPTCanConfidentialAmount, 0x00000080)) \
LSF_FLAG(lsfMPTCanClawback, 0x00000040)) \
\
LEDGER_OBJECT(MPTokenIssuanceMutable, \
LSF_FLAG(lsmfMPTCanMutateCanLock, 0x00000002) \
@@ -184,8 +183,7 @@ enum LedgerEntryType : std::uint16_t {
LSF_FLAG(lsmfMPTCanMutateCanTransfer, 0x00000020) \
LSF_FLAG(lsmfMPTCanMutateCanClawback, 0x00000040) \
LSF_FLAG(lsmfMPTCanMutateMetadata, 0x00010000) \
LSF_FLAG(lsmfMPTCanMutateTransferFee, 0x00020000) \
LSF_FLAG(lsmfMPTCannotMutateCanConfidentialAmount, 0x00040000)) \
LSF_FLAG(lsmfMPTCanMutateTransferFee, 0x00020000)) \
\
LEDGER_OBJECT(MPToken, \
LSF_FLAG2(lsfMPTLocked, 0x00000001) \

View File

@@ -307,46 +307,4 @@ std::size_t constexpr permissionMaxSize = 10;
/** The maximum number of transactions that can be in a batch. */
std::size_t constexpr maxBatchTxCount = 8;
/** Length of one component of EC ElGamal ciphertext */
std::size_t constexpr ecGamalEncryptedLength = 33;
/** EC ElGamal ciphertext length: two 33-byte components concatenated */
std::size_t constexpr ecGamalEncryptedTotalLength = ecGamalEncryptedLength * 2;
/** Length of equality ZKProof in bytes */
std::size_t constexpr ecEqualityProofLength = 98;
/** Length of EC point (compressed) */
std::size_t constexpr compressedECPointLength = 33;
/** Length of EC public key (compressed) */
std::size_t constexpr ecPubKeyLength = compressedECPointLength;
/** Length of EC private key in bytes */
std::size_t constexpr ecPrivKeyLength = 32;
/** Length of the EC blinding factor in bytes */
std::size_t constexpr ecBlindingFactorLength = 32;
/** Length of Schnorr ZKProof for public key registration in bytes */
std::size_t constexpr ecSchnorrProofLength = 65;
/** Length of ElGamal Pedersen linkage proof in bytes */
std::size_t constexpr ecPedersenProofLength = 195;
/** Length of Pedersen Commitment (compressed) */
std::size_t constexpr ecPedersenCommitmentLength = compressedECPointLength;
/** Length of single bulletproof (range proof for 1 commitment) in bytes */
std::size_t constexpr ecSingleBulletproofLength = 688;
/** Length of double bulletproof (range proof for 2 commitments) in bytes */
std::size_t constexpr ecDoubleBulletproofLength = 754;
/** Compressed EC point prefix for even y-coordinate */
std::uint8_t constexpr ecCompressedPrefixEvenY = 0x02;
/** Compressed EC point prefix for odd y-coordinate */
std::uint8_t constexpr ecCompressedPrefixOddY = 0x03;
} // namespace xrpl

View File

@@ -153,16 +153,13 @@ private:
Expected<void, std::string>
checkBatchMultiSign(STObject const& batchSigner, Rules const& rules) const;
void
buildBatchTxnIds();
STBase*
copy(std::size_t n, void* buf) const override;
STBase*
move(std::size_t n, void* buf) override;
friend class detail::STVar;
std::vector<uint256> batchTxnIds_;
mutable std::vector<uint256> batchTxnIds_;
};
bool

View File

@@ -121,7 +121,6 @@ enum TEMcodes : TERUnderlyingType {
temARRAY_TOO_LARGE,
temBAD_TRANSFER_FEE,
temINVALID_INNER_BATCH,
temBAD_CIPHERTEXT,
};
//------------------------------------------------------------------------------
@@ -347,7 +346,6 @@ enum TECcodes : TERUnderlyingType {
// backward compatibility with historical data on non-prod networks, can be
// reclaimed after those networks reset.
tecNO_DELEGATE_PERMISSION = 198,
tecBAD_PROOF = 199,
};
//------------------------------------------------------------------------------

View File

@@ -138,8 +138,7 @@ inline constexpr FlagValue tfUniversalMask = ~tfUniversal;
TF_FLAG(tfMPTCanEscrow, lsfMPTCanEscrow) \
TF_FLAG(tfMPTCanTrade, lsfMPTCanTrade) \
TF_FLAG(tfMPTCanTransfer, lsfMPTCanTransfer) \
TF_FLAG(tfMPTCanClawback, lsfMPTCanClawback) \
TF_FLAG(tfMPTCanConfidentialAmount, lsfMPTCanConfidentialAmount), \
TF_FLAG(tfMPTCanClawback, lsfMPTCanClawback), \
MASK_ADJ(0)) \
\
TRANSACTION(MPTokenAuthorize, \
@@ -348,12 +347,10 @@ inline constexpr FlagValue tmfMPTCanMutateCanTransfer = lsmfMPTCanMutateCanTrans
inline constexpr FlagValue tmfMPTCanMutateCanClawback = lsmfMPTCanMutateCanClawback;
inline constexpr FlagValue tmfMPTCanMutateMetadata = lsmfMPTCanMutateMetadata;
inline constexpr FlagValue tmfMPTCanMutateTransferFee = lsmfMPTCanMutateTransferFee;
inline constexpr FlagValue tmfMPTCannotMutateCanConfidentialAmount =
lsmfMPTCannotMutateCanConfidentialAmount;
inline constexpr FlagValue tmfMPTokenIssuanceCreateMutableMask = ~(
tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow |
tmfMPTCanMutateCanTrade | tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback |
tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee | tmfMPTCannotMutateCanConfidentialAmount);
inline constexpr FlagValue tmfMPTokenIssuanceCreateMutableMask =
~(tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow |
tmfMPTCanMutateCanTrade | tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback |
tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee);
// MPTokenIssuanceSet MutableFlags:
// Set or Clear flags.
@@ -370,13 +367,10 @@ inline constexpr FlagValue tmfMPTSetCanTransfer = 0x00000100;
inline constexpr FlagValue tmfMPTClearCanTransfer = 0x00000200;
inline constexpr FlagValue tmfMPTSetCanClawback = 0x00000400;
inline constexpr FlagValue tmfMPTClearCanClawback = 0x00000800;
inline constexpr FlagValue tmfMPTSetCanConfidentialAmount = 0x00001000;
inline constexpr FlagValue tmfMPTClearCanConfidentialAmount = 0x00002000;
inline constexpr FlagValue tmfMPTokenIssuanceSetMutableMask =
~(tmfMPTSetCanLock | tmfMPTClearCanLock | tmfMPTSetRequireAuth | tmfMPTClearRequireAuth |
tmfMPTSetCanEscrow | tmfMPTClearCanEscrow | tmfMPTSetCanTrade | tmfMPTClearCanTrade |
tmfMPTSetCanTransfer | tmfMPTClearCanTransfer | tmfMPTSetCanClawback |
tmfMPTClearCanClawback | tmfMPTSetCanConfidentialAmount | tmfMPTClearCanConfidentialAmount);
inline constexpr FlagValue tmfMPTokenIssuanceSetMutableMask = ~(
tmfMPTSetCanLock | tmfMPTClearCanLock | tmfMPTSetRequireAuth | tmfMPTClearRequireAuth |
tmfMPTSetCanEscrow | tmfMPTClearCanEscrow | tmfMPTSetCanTrade | tmfMPTClearCanTrade |
tmfMPTSetCanTransfer | tmfMPTClearCanTransfer | tmfMPTSetCanClawback | tmfMPTClearCanClawback);
// Prior to fixRemoveNFTokenAutoTrustLine, transfer of an NFToken between accounts allowed a
// TrustLine to be added to the issuer of that token without explicit permission from that issuer.

View File

@@ -15,11 +15,10 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FEATURE(BatchV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(ConfidentialTransfer, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (BatchInnerSigs, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
@@ -33,6 +32,7 @@ XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultN
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Batch, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
// Check flags in Credential transactions

View File

@@ -385,41 +385,32 @@ LEDGER_ENTRY(ltAMM, 0x0079, AMM, amm, ({
\sa keylet::mptIssuance
*/
LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({
{sfIssuer, soeREQUIRED},
{sfSequence, soeREQUIRED},
{sfTransferFee, soeDEFAULT},
{sfOwnerNode, soeREQUIRED},
{sfAssetScale, soeDEFAULT},
{sfMaximumAmount, soeOPTIONAL},
{sfOutstandingAmount, soeREQUIRED},
{sfLockedAmount, soeOPTIONAL},
{sfMPTokenMetadata, soeOPTIONAL},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfDomainID, soeOPTIONAL},
{sfMutableFlags, soeDEFAULT},
{sfIssuerEncryptionKey, soeOPTIONAL},
{sfAuditorEncryptionKey, soeOPTIONAL},
{sfConfidentialOutstandingAmount, soeDEFAULT},
{sfIssuer, soeREQUIRED},
{sfSequence, soeREQUIRED},
{sfTransferFee, soeDEFAULT},
{sfOwnerNode, soeREQUIRED},
{sfAssetScale, soeDEFAULT},
{sfMaximumAmount, soeOPTIONAL},
{sfOutstandingAmount, soeREQUIRED},
{sfLockedAmount, soeOPTIONAL},
{sfMPTokenMetadata, soeOPTIONAL},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfDomainID, soeOPTIONAL},
{sfMutableFlags, soeDEFAULT},
}))
/** A ledger object which tracks MPToken
\sa keylet::mptoken
*/
LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({
{sfAccount, soeREQUIRED},
{sfMPTokenIssuanceID, soeREQUIRED},
{sfMPTAmount, soeDEFAULT},
{sfLockedAmount, soeOPTIONAL},
{sfOwnerNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfConfidentialBalanceInbox, soeOPTIONAL},
{sfConfidentialBalanceSpending, soeOPTIONAL},
{sfConfidentialBalanceVersion, soeDEFAULT},
{sfIssuerEncryptedBalance, soeOPTIONAL},
{sfAuditorEncryptedBalance, soeOPTIONAL},
{sfHolderEncryptionKey, soeOPTIONAL},
{sfAccount, soeREQUIRED},
{sfMPTokenIssuanceID, soeREQUIRED},
{sfMPTAmount, soeDEFAULT},
{sfLockedAmount, soeOPTIONAL},
{sfOwnerNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
/** A ledger object which tracks Oracle

View File

@@ -113,7 +113,6 @@ TYPED_SFIELD(sfInterestRate, UINT32, 65) // 1/10 basis points (bi
TYPED_SFIELD(sfLateInterestRate, UINT32, 66) // 1/10 basis points (bips)
TYPED_SFIELD(sfCloseInterestRate, UINT32, 67) // 1/10 basis points (bips)
TYPED_SFIELD(sfOverpaymentInterestRate, UINT32, 68) // 1/10 basis points (bips)
TYPED_SFIELD(sfConfidentialBalanceVersion, UINT32, 69)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -147,7 +146,6 @@ TYPED_SFIELD(sfSubjectNode, UINT64, 28)
TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::sMD_BaseTen|SField::sMD_Default)
TYPED_SFIELD(sfVaultNode, UINT64, 30)
TYPED_SFIELD(sfLoanBrokerNode, UINT64, 31)
TYPED_SFIELD(sfConfidentialOutstandingAmount, UINT64, 32, SField::sMD_BaseTen|SField::sMD_Default)
// 128-bit
TYPED_SFIELD(sfEmailHash, UINT128, 1)
@@ -205,7 +203,6 @@ TYPED_SFIELD(sfParentBatchID, UINT256, 36)
TYPED_SFIELD(sfLoanBrokerID, UINT256, 37,
SField::sMD_PseudoAccount | SField::sMD_Default)
TYPED_SFIELD(sfLoanID, UINT256, 38)
TYPED_SFIELD(sfBlindingFactor, UINT256, 39)
// number (common)
TYPED_SFIELD(sfNumber, NUMBER, 1)
@@ -299,21 +296,6 @@ TYPED_SFIELD(sfAssetClass, VL, 28)
TYPED_SFIELD(sfProvider, VL, 29)
TYPED_SFIELD(sfMPTokenMetadata, VL, 30)
TYPED_SFIELD(sfCredentialType, VL, 31)
TYPED_SFIELD(sfConfidentialBalanceInbox, VL, 32)
TYPED_SFIELD(sfConfidentialBalanceSpending, VL, 33)
TYPED_SFIELD(sfIssuerEncryptedBalance, VL, 34)
TYPED_SFIELD(sfIssuerEncryptionKey, VL, 35)
TYPED_SFIELD(sfHolderEncryptionKey, VL, 36)
TYPED_SFIELD(sfZKProof, VL, 37)
TYPED_SFIELD(sfHolderEncryptedAmount, VL, 38)
TYPED_SFIELD(sfIssuerEncryptedAmount, VL, 39)
TYPED_SFIELD(sfSenderEncryptedAmount, VL, 40)
TYPED_SFIELD(sfDestinationEncryptedAmount, VL, 41)
TYPED_SFIELD(sfAuditorEncryptedBalance, VL, 42)
TYPED_SFIELD(sfAuditorEncryptedAmount, VL, 43)
TYPED_SFIELD(sfAuditorEncryptionKey, VL, 44)
TYPED_SFIELD(sfAmountCommitment, VL, 45)
TYPED_SFIELD(sfBalanceCommitment, VL, 46)
// account (common)
TYPED_SFIELD(sfAccount, ACCOUNT, 1)

View File

@@ -734,8 +734,6 @@ TRANSACTION(ttMPTOKEN_ISSUANCE_SET, 56, MPTokenIssuanceSet,
{sfMPTokenMetadata, soeOPTIONAL},
{sfTransferFee, soeOPTIONAL},
{sfMutableFlags, soeOPTIONAL},
{sfIssuerEncryptionKey, soeOPTIONAL},
{sfAuditorEncryptionKey, soeOPTIONAL},
}))
/** This transaction type authorizes a MPToken instance */
@@ -938,7 +936,7 @@ TRANSACTION(ttVAULT_CLAWBACK, 70, VaultClawback,
#endif
TRANSACTION(ttBATCH, 71, Batch,
Delegation::notDelegable,
featureBatchV1_1,
featureBatch,
noPriv,
({
{sfRawTransactions, soeREQUIRED},
@@ -1078,90 +1076,6 @@ TRANSACTION(ttLOAN_PAY, 84, LoanPay,
{sfAmount, soeREQUIRED, soeMPTSupported},
}))
/** This transaction type converts into confidential MPT balance. */
#if TRANSACTION_INCLUDE
#include <xrpl/tx/transactors/token/ConfidentialMPTConvert.h>
#endif
TRANSACTION(ttCONFIDENTIAL_MPT_CONVERT, 85, ConfidentialMPTConvert,
Delegation::delegable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfMPTAmount, soeREQUIRED},
{sfHolderEncryptionKey, soeOPTIONAL},
{sfHolderEncryptedAmount, soeREQUIRED},
{sfIssuerEncryptedAmount, soeREQUIRED},
{sfAuditorEncryptedAmount, soeOPTIONAL},
{sfBlindingFactor, soeREQUIRED},
{sfZKProof, soeOPTIONAL},
}))
/** This transaction type merges MPT inbox. */
#if TRANSACTION_INCLUDE
#include <xrpl/tx/transactors/token/ConfidentialMPTMergeInbox.h>
#endif
TRANSACTION(ttCONFIDENTIAL_MPT_MERGE_INBOX, 86, ConfidentialMPTMergeInbox,
Delegation::delegable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
}))
/** This transaction type converts back into public MPT balance. */
#if TRANSACTION_INCLUDE
#include <xrpl/tx/transactors/token/ConfidentialMPTConvertBack.h>
#endif
TRANSACTION(ttCONFIDENTIAL_MPT_CONVERT_BACK, 87, ConfidentialMPTConvertBack,
Delegation::delegable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfMPTAmount, soeREQUIRED},
{sfHolderEncryptedAmount, soeREQUIRED},
{sfIssuerEncryptedAmount, soeREQUIRED},
{sfAuditorEncryptedAmount, soeOPTIONAL},
{sfBlindingFactor, soeREQUIRED},
{sfZKProof, soeREQUIRED},
{sfBalanceCommitment, soeREQUIRED},
}))
#if TRANSACTION_INCLUDE
#include <xrpl/tx/transactors/token/ConfidentialMPTSend.h>
#endif
TRANSACTION(ttCONFIDENTIAL_MPT_SEND, 88, ConfidentialMPTSend,
Delegation::delegable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfDestination, soeREQUIRED},
{sfSenderEncryptedAmount, soeREQUIRED},
{sfDestinationEncryptedAmount, soeREQUIRED},
{sfIssuerEncryptedAmount, soeREQUIRED},
{sfAuditorEncryptedAmount, soeOPTIONAL},
{sfZKProof, soeREQUIRED},
{sfAmountCommitment, soeREQUIRED},
{sfBalanceCommitment, soeREQUIRED},
{sfCredentialIDs, soeOPTIONAL},
}))
#if TRANSACTION_INCLUDE
#include <xrpl/tx/transactors/token/ConfidentialMPTClawback.h>
#endif
TRANSACTION(ttCONFIDENTIAL_MPT_CLAWBACK, 89, ConfidentialMPTClawback,
Delegation::delegable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfHolder, soeREQUIRED},
{sfMPTAmount, soeREQUIRED},
{sfZKProof, soeREQUIRED},
}))
/** This system-generated transaction type is used to update the status of the various amendments.
For details, see: https://xrpl.org/amendments.html

View File

@@ -147,150 +147,6 @@ public:
{
return this->sle_->at(sfPreviousTxnLgrSeq);
}
/**
* @brief Get sfConfidentialBalanceInbox (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getConfidentialBalanceInbox() const
{
if (hasConfidentialBalanceInbox())
return this->sle_->at(sfConfidentialBalanceInbox);
return std::nullopt;
}
/**
* @brief Check if sfConfidentialBalanceInbox is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasConfidentialBalanceInbox() const
{
return this->sle_->isFieldPresent(sfConfidentialBalanceInbox);
}
/**
* @brief Get sfConfidentialBalanceSpending (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getConfidentialBalanceSpending() const
{
if (hasConfidentialBalanceSpending())
return this->sle_->at(sfConfidentialBalanceSpending);
return std::nullopt;
}
/**
* @brief Check if sfConfidentialBalanceSpending is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasConfidentialBalanceSpending() const
{
return this->sle_->isFieldPresent(sfConfidentialBalanceSpending);
}
/**
* @brief Get sfConfidentialBalanceVersion (soeDEFAULT)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getConfidentialBalanceVersion() const
{
if (hasConfidentialBalanceVersion())
return this->sle_->at(sfConfidentialBalanceVersion);
return std::nullopt;
}
/**
* @brief Check if sfConfidentialBalanceVersion is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasConfidentialBalanceVersion() const
{
return this->sle_->isFieldPresent(sfConfidentialBalanceVersion);
}
/**
* @brief Get sfIssuerEncryptedBalance (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getIssuerEncryptedBalance() const
{
if (hasIssuerEncryptedBalance())
return this->sle_->at(sfIssuerEncryptedBalance);
return std::nullopt;
}
/**
* @brief Check if sfIssuerEncryptedBalance is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasIssuerEncryptedBalance() const
{
return this->sle_->isFieldPresent(sfIssuerEncryptedBalance);
}
/**
* @brief Get sfAuditorEncryptedBalance (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getAuditorEncryptedBalance() const
{
if (hasAuditorEncryptedBalance())
return this->sle_->at(sfAuditorEncryptedBalance);
return std::nullopt;
}
/**
* @brief Check if sfAuditorEncryptedBalance is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAuditorEncryptedBalance() const
{
return this->sle_->isFieldPresent(sfAuditorEncryptedBalance);
}
/**
* @brief Get sfHolderEncryptionKey (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getHolderEncryptionKey() const
{
if (hasHolderEncryptionKey())
return this->sle_->at(sfHolderEncryptionKey);
return std::nullopt;
}
/**
* @brief Check if sfHolderEncryptionKey is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasHolderEncryptionKey() const
{
return this->sle_->isFieldPresent(sfHolderEncryptionKey);
}
};
/**
@@ -414,72 +270,6 @@ public:
return *this;
}
/**
* @brief Set sfConfidentialBalanceInbox (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenBuilder&
setConfidentialBalanceInbox(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfConfidentialBalanceInbox] = value;
return *this;
}
/**
* @brief Set sfConfidentialBalanceSpending (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenBuilder&
setConfidentialBalanceSpending(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfConfidentialBalanceSpending] = value;
return *this;
}
/**
* @brief Set sfConfidentialBalanceVersion (soeDEFAULT)
* @return Reference to this builder for method chaining.
*/
MPTokenBuilder&
setConfidentialBalanceVersion(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfConfidentialBalanceVersion] = value;
return *this;
}
/**
* @brief Set sfIssuerEncryptedBalance (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenBuilder&
setIssuerEncryptedBalance(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfIssuerEncryptedBalance] = value;
return *this;
}
/**
* @brief Set sfAuditorEncryptedBalance (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenBuilder&
setAuditorEncryptedBalance(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAuditorEncryptedBalance] = value;
return *this;
}
/**
* @brief Set sfHolderEncryptionKey (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenBuilder&
setHolderEncryptionKey(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfHolderEncryptionKey] = value;
return *this;
}
/**
* @brief Build and return the completed MPToken wrapper.
* @param index The ledger entry index.

View File

@@ -278,78 +278,6 @@ public:
{
return this->sle_->isFieldPresent(sfMutableFlags);
}
/**
* @brief Get sfIssuerEncryptionKey (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getIssuerEncryptionKey() const
{
if (hasIssuerEncryptionKey())
return this->sle_->at(sfIssuerEncryptionKey);
return std::nullopt;
}
/**
* @brief Check if sfIssuerEncryptionKey is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasIssuerEncryptionKey() const
{
return this->sle_->isFieldPresent(sfIssuerEncryptionKey);
}
/**
* @brief Get sfAuditorEncryptionKey (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getAuditorEncryptionKey() const
{
if (hasAuditorEncryptionKey())
return this->sle_->at(sfAuditorEncryptionKey);
return std::nullopt;
}
/**
* @brief Check if sfAuditorEncryptionKey is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAuditorEncryptionKey() const
{
return this->sle_->isFieldPresent(sfAuditorEncryptionKey);
}
/**
* @brief Get sfConfidentialOutstandingAmount (soeDEFAULT)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT64::type::value_type>
getConfidentialOutstandingAmount() const
{
if (hasConfidentialOutstandingAmount())
return this->sle_->at(sfConfidentialOutstandingAmount);
return std::nullopt;
}
/**
* @brief Check if sfConfidentialOutstandingAmount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasConfidentialOutstandingAmount() const
{
return this->sle_->isFieldPresent(sfConfidentialOutstandingAmount);
}
};
/**
@@ -541,39 +469,6 @@ public:
return *this;
}
/**
* @brief Set sfIssuerEncryptionKey (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenIssuanceBuilder&
setIssuerEncryptionKey(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfIssuerEncryptionKey] = value;
return *this;
}
/**
* @brief Set sfAuditorEncryptionKey (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenIssuanceBuilder&
setAuditorEncryptionKey(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAuditorEncryptionKey] = value;
return *this;
}
/**
* @brief Set sfConfidentialOutstandingAmount (soeDEFAULT)
* @return Reference to this builder for method chaining.
*/
MPTokenIssuanceBuilder&
setConfidentialOutstandingAmount(std::decay_t<typename SF_UINT64::type::value_type> const& value)
{
object_[sfConfidentialOutstandingAmount] = value;
return *this;
}
/**
* @brief Build and return the completed MPTokenIssuance wrapper.
* @param index The ledger entry index.

View File

@@ -20,7 +20,7 @@ class BatchBuilder;
*
* Type: ttBATCH (71)
* Delegable: Delegation::notDelegable
* Amendment: featureBatchV1_1
* Amendment: featureBatch
* Privileges: noPriv
*
* Immutable wrapper around STTx providing type-safe field access.

View File

@@ -1,201 +0,0 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class ConfidentialMPTClawbackBuilder;
/**
* @brief Transaction: ConfidentialMPTClawback
*
* Type: ttCONFIDENTIAL_MPT_CLAWBACK (89)
* Delegable: Delegation::delegable
* Amendment: featureConfidentialTransfer
* Privileges: noPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use ConfidentialMPTClawbackBuilder to construct new transactions.
*/
class ConfidentialMPTClawback : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttCONFIDENTIAL_MPT_CLAWBACK;
/**
* @brief Construct a ConfidentialMPTClawback transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit ConfidentialMPTClawback(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTClawback");
}
}
// Transaction-specific field getters
/**
* @brief Get sfMPTokenIssuanceID (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT192::type::value_type
getMPTokenIssuanceID() const
{
return this->tx_->at(sfMPTokenIssuanceID);
}
/**
* @brief Get sfHolder (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_ACCOUNT::type::value_type
getHolder() const
{
return this->tx_->at(sfHolder);
}
/**
* @brief Get sfMPTAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT64::type::value_type
getMPTAmount() const
{
return this->tx_->at(sfMPTAmount);
}
/**
* @brief Get sfZKProof (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getZKProof() const
{
return this->tx_->at(sfZKProof);
}
};
/**
* @brief Builder for ConfidentialMPTClawback transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses Json::Value internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class ConfidentialMPTClawbackBuilder : public TransactionBuilderBase<ConfidentialMPTClawbackBuilder>
{
public:
/**
* @brief Construct a new ConfidentialMPTClawbackBuilder with required fields.
* @param account The account initiating the transaction.
* @param mPTokenIssuanceID The sfMPTokenIssuanceID field value.
* @param holder The sfHolder field value.
* @param mPTAmount The sfMPTAmount field value.
* @param zKProof The sfZKProof field value.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
ConfidentialMPTClawbackBuilder(SF_ACCOUNT::type::value_type account,
std::decay_t<typename SF_UINT192::type::value_type> const& mPTokenIssuanceID, std::decay_t<typename SF_ACCOUNT::type::value_type> const& holder, std::decay_t<typename SF_UINT64::type::value_type> const& mPTAmount, std::decay_t<typename SF_VL::type::value_type> const& zKProof, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<ConfidentialMPTClawbackBuilder>(ttCONFIDENTIAL_MPT_CLAWBACK, account, sequence, fee)
{
setMPTokenIssuanceID(mPTokenIssuanceID);
setHolder(holder);
setMPTAmount(mPTAmount);
setZKProof(zKProof);
}
/**
* @brief Construct a ConfidentialMPTClawbackBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
ConfidentialMPTClawbackBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttCONFIDENTIAL_MPT_CLAWBACK)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTClawbackBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfMPTokenIssuanceID (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTClawbackBuilder&
setMPTokenIssuanceID(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfMPTokenIssuanceID] = value;
return *this;
}
/**
* @brief Set sfHolder (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTClawbackBuilder&
setHolder(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfHolder] = value;
return *this;
}
/**
* @brief Set sfMPTAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTClawbackBuilder&
setMPTAmount(std::decay_t<typename SF_UINT64::type::value_type> const& value)
{
object_[sfMPTAmount] = value;
return *this;
}
/**
* @brief Set sfZKProof (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTClawbackBuilder&
setZKProof(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfZKProof] = value;
return *this;
}
/**
* @brief Build and return the ConfidentialMPTClawback wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
ConfidentialMPTClawback
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return ConfidentialMPTClawback{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -1,336 +0,0 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class ConfidentialMPTConvertBuilder;
/**
* @brief Transaction: ConfidentialMPTConvert
*
* Type: ttCONFIDENTIAL_MPT_CONVERT (85)
* Delegable: Delegation::delegable
* Amendment: featureConfidentialTransfer
* Privileges: noPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use ConfidentialMPTConvertBuilder to construct new transactions.
*/
class ConfidentialMPTConvert : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttCONFIDENTIAL_MPT_CONVERT;
/**
* @brief Construct a ConfidentialMPTConvert transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit ConfidentialMPTConvert(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTConvert");
}
}
// Transaction-specific field getters
/**
* @brief Get sfMPTokenIssuanceID (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT192::type::value_type
getMPTokenIssuanceID() const
{
return this->tx_->at(sfMPTokenIssuanceID);
}
/**
* @brief Get sfMPTAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT64::type::value_type
getMPTAmount() const
{
return this->tx_->at(sfMPTAmount);
}
/**
* @brief Get sfHolderEncryptionKey (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getHolderEncryptionKey() const
{
if (hasHolderEncryptionKey())
{
return this->tx_->at(sfHolderEncryptionKey);
}
return std::nullopt;
}
/**
* @brief Check if sfHolderEncryptionKey is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasHolderEncryptionKey() const
{
return this->tx_->isFieldPresent(sfHolderEncryptionKey);
}
/**
* @brief Get sfHolderEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getHolderEncryptedAmount() const
{
return this->tx_->at(sfHolderEncryptedAmount);
}
/**
* @brief Get sfIssuerEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getIssuerEncryptedAmount() const
{
return this->tx_->at(sfIssuerEncryptedAmount);
}
/**
* @brief Get sfAuditorEncryptedAmount (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getAuditorEncryptedAmount() const
{
if (hasAuditorEncryptedAmount())
{
return this->tx_->at(sfAuditorEncryptedAmount);
}
return std::nullopt;
}
/**
* @brief Check if sfAuditorEncryptedAmount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAuditorEncryptedAmount() const
{
return this->tx_->isFieldPresent(sfAuditorEncryptedAmount);
}
/**
* @brief Get sfBlindingFactor (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT256::type::value_type
getBlindingFactor() const
{
return this->tx_->at(sfBlindingFactor);
}
/**
* @brief Get sfZKProof (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getZKProof() const
{
if (hasZKProof())
{
return this->tx_->at(sfZKProof);
}
return std::nullopt;
}
/**
* @brief Check if sfZKProof is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasZKProof() const
{
return this->tx_->isFieldPresent(sfZKProof);
}
};
/**
* @brief Builder for ConfidentialMPTConvert transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses Json::Value internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class ConfidentialMPTConvertBuilder : public TransactionBuilderBase<ConfidentialMPTConvertBuilder>
{
public:
/**
* @brief Construct a new ConfidentialMPTConvertBuilder with required fields.
* @param account The account initiating the transaction.
* @param mPTokenIssuanceID The sfMPTokenIssuanceID field value.
* @param mPTAmount The sfMPTAmount field value.
* @param holderEncryptedAmount The sfHolderEncryptedAmount field value.
* @param issuerEncryptedAmount The sfIssuerEncryptedAmount field value.
* @param blindingFactor The sfBlindingFactor field value.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
ConfidentialMPTConvertBuilder(SF_ACCOUNT::type::value_type account,
std::decay_t<typename SF_UINT192::type::value_type> const& mPTokenIssuanceID, std::decay_t<typename SF_UINT64::type::value_type> const& mPTAmount, std::decay_t<typename SF_VL::type::value_type> const& holderEncryptedAmount, std::decay_t<typename SF_VL::type::value_type> const& issuerEncryptedAmount, std::decay_t<typename SF_UINT256::type::value_type> const& blindingFactor, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<ConfidentialMPTConvertBuilder>(ttCONFIDENTIAL_MPT_CONVERT, account, sequence, fee)
{
setMPTokenIssuanceID(mPTokenIssuanceID);
setMPTAmount(mPTAmount);
setHolderEncryptedAmount(holderEncryptedAmount);
setIssuerEncryptedAmount(issuerEncryptedAmount);
setBlindingFactor(blindingFactor);
}
/**
* @brief Construct a ConfidentialMPTConvertBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
ConfidentialMPTConvertBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttCONFIDENTIAL_MPT_CONVERT)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTConvertBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfMPTokenIssuanceID (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setMPTokenIssuanceID(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfMPTokenIssuanceID] = value;
return *this;
}
/**
* @brief Set sfMPTAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setMPTAmount(std::decay_t<typename SF_UINT64::type::value_type> const& value)
{
object_[sfMPTAmount] = value;
return *this;
}
/**
* @brief Set sfHolderEncryptionKey (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setHolderEncryptionKey(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfHolderEncryptionKey] = value;
return *this;
}
/**
* @brief Set sfHolderEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setHolderEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfHolderEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfIssuerEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setIssuerEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfIssuerEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfAuditorEncryptedAmount (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setAuditorEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAuditorEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfBlindingFactor (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setBlindingFactor(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfBlindingFactor] = value;
return *this;
}
/**
* @brief Set sfZKProof (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBuilder&
setZKProof(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfZKProof] = value;
return *this;
}
/**
* @brief Build and return the ConfidentialMPTConvert wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
ConfidentialMPTConvert
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return ConfidentialMPTConvert{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -1,310 +0,0 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class ConfidentialMPTConvertBackBuilder;
/**
* @brief Transaction: ConfidentialMPTConvertBack
*
* Type: ttCONFIDENTIAL_MPT_CONVERT_BACK (87)
* Delegable: Delegation::delegable
* Amendment: featureConfidentialTransfer
* Privileges: noPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use ConfidentialMPTConvertBackBuilder to construct new transactions.
*/
class ConfidentialMPTConvertBack : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttCONFIDENTIAL_MPT_CONVERT_BACK;
/**
* @brief Construct a ConfidentialMPTConvertBack transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit ConfidentialMPTConvertBack(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTConvertBack");
}
}
// Transaction-specific field getters
/**
* @brief Get sfMPTokenIssuanceID (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT192::type::value_type
getMPTokenIssuanceID() const
{
return this->tx_->at(sfMPTokenIssuanceID);
}
/**
* @brief Get sfMPTAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT64::type::value_type
getMPTAmount() const
{
return this->tx_->at(sfMPTAmount);
}
/**
* @brief Get sfHolderEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getHolderEncryptedAmount() const
{
return this->tx_->at(sfHolderEncryptedAmount);
}
/**
* @brief Get sfIssuerEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getIssuerEncryptedAmount() const
{
return this->tx_->at(sfIssuerEncryptedAmount);
}
/**
* @brief Get sfAuditorEncryptedAmount (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getAuditorEncryptedAmount() const
{
if (hasAuditorEncryptedAmount())
{
return this->tx_->at(sfAuditorEncryptedAmount);
}
return std::nullopt;
}
/**
* @brief Check if sfAuditorEncryptedAmount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAuditorEncryptedAmount() const
{
return this->tx_->isFieldPresent(sfAuditorEncryptedAmount);
}
/**
* @brief Get sfBlindingFactor (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT256::type::value_type
getBlindingFactor() const
{
return this->tx_->at(sfBlindingFactor);
}
/**
* @brief Get sfZKProof (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getZKProof() const
{
return this->tx_->at(sfZKProof);
}
/**
* @brief Get sfBalanceCommitment (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getBalanceCommitment() const
{
return this->tx_->at(sfBalanceCommitment);
}
};
/**
* @brief Builder for ConfidentialMPTConvertBack transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses Json::Value internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class ConfidentialMPTConvertBackBuilder : public TransactionBuilderBase<ConfidentialMPTConvertBackBuilder>
{
public:
/**
* @brief Construct a new ConfidentialMPTConvertBackBuilder with required fields.
* @param account The account initiating the transaction.
* @param mPTokenIssuanceID The sfMPTokenIssuanceID field value.
* @param mPTAmount The sfMPTAmount field value.
* @param holderEncryptedAmount The sfHolderEncryptedAmount field value.
* @param issuerEncryptedAmount The sfIssuerEncryptedAmount field value.
* @param blindingFactor The sfBlindingFactor field value.
* @param zKProof The sfZKProof field value.
* @param balanceCommitment The sfBalanceCommitment field value.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
ConfidentialMPTConvertBackBuilder(SF_ACCOUNT::type::value_type account,
std::decay_t<typename SF_UINT192::type::value_type> const& mPTokenIssuanceID, std::decay_t<typename SF_UINT64::type::value_type> const& mPTAmount, std::decay_t<typename SF_VL::type::value_type> const& holderEncryptedAmount, std::decay_t<typename SF_VL::type::value_type> const& issuerEncryptedAmount, std::decay_t<typename SF_UINT256::type::value_type> const& blindingFactor, std::decay_t<typename SF_VL::type::value_type> const& zKProof, std::decay_t<typename SF_VL::type::value_type> const& balanceCommitment, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<ConfidentialMPTConvertBackBuilder>(ttCONFIDENTIAL_MPT_CONVERT_BACK, account, sequence, fee)
{
setMPTokenIssuanceID(mPTokenIssuanceID);
setMPTAmount(mPTAmount);
setHolderEncryptedAmount(holderEncryptedAmount);
setIssuerEncryptedAmount(issuerEncryptedAmount);
setBlindingFactor(blindingFactor);
setZKProof(zKProof);
setBalanceCommitment(balanceCommitment);
}
/**
* @brief Construct a ConfidentialMPTConvertBackBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
ConfidentialMPTConvertBackBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttCONFIDENTIAL_MPT_CONVERT_BACK)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTConvertBackBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfMPTokenIssuanceID (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setMPTokenIssuanceID(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfMPTokenIssuanceID] = value;
return *this;
}
/**
* @brief Set sfMPTAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setMPTAmount(std::decay_t<typename SF_UINT64::type::value_type> const& value)
{
object_[sfMPTAmount] = value;
return *this;
}
/**
* @brief Set sfHolderEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setHolderEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfHolderEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfIssuerEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setIssuerEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfIssuerEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfAuditorEncryptedAmount (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setAuditorEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAuditorEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfBlindingFactor (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setBlindingFactor(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfBlindingFactor] = value;
return *this;
}
/**
* @brief Set sfZKProof (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setZKProof(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfZKProof] = value;
return *this;
}
/**
* @brief Set sfBalanceCommitment (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTConvertBackBuilder&
setBalanceCommitment(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfBalanceCommitment] = value;
return *this;
}
/**
* @brief Build and return the ConfidentialMPTConvertBack wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
ConfidentialMPTConvertBack
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return ConfidentialMPTConvertBack{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -1,129 +0,0 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class ConfidentialMPTMergeInboxBuilder;
/**
* @brief Transaction: ConfidentialMPTMergeInbox
*
* Type: ttCONFIDENTIAL_MPT_MERGE_INBOX (86)
* Delegable: Delegation::delegable
* Amendment: featureConfidentialTransfer
* Privileges: noPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use ConfidentialMPTMergeInboxBuilder to construct new transactions.
*/
class ConfidentialMPTMergeInbox : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttCONFIDENTIAL_MPT_MERGE_INBOX;
/**
* @brief Construct a ConfidentialMPTMergeInbox transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit ConfidentialMPTMergeInbox(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTMergeInbox");
}
}
// Transaction-specific field getters
/**
* @brief Get sfMPTokenIssuanceID (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT192::type::value_type
getMPTokenIssuanceID() const
{
return this->tx_->at(sfMPTokenIssuanceID);
}
};
/**
* @brief Builder for ConfidentialMPTMergeInbox transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses Json::Value internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class ConfidentialMPTMergeInboxBuilder : public TransactionBuilderBase<ConfidentialMPTMergeInboxBuilder>
{
public:
/**
* @brief Construct a new ConfidentialMPTMergeInboxBuilder with required fields.
* @param account The account initiating the transaction.
* @param mPTokenIssuanceID The sfMPTokenIssuanceID field value.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
ConfidentialMPTMergeInboxBuilder(SF_ACCOUNT::type::value_type account,
std::decay_t<typename SF_UINT192::type::value_type> const& mPTokenIssuanceID, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<ConfidentialMPTMergeInboxBuilder>(ttCONFIDENTIAL_MPT_MERGE_INBOX, account, sequence, fee)
{
setMPTokenIssuanceID(mPTokenIssuanceID);
}
/**
* @brief Construct a ConfidentialMPTMergeInboxBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
ConfidentialMPTMergeInboxBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttCONFIDENTIAL_MPT_MERGE_INBOX)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTMergeInboxBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfMPTokenIssuanceID (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTMergeInboxBuilder&
setMPTokenIssuanceID(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfMPTokenIssuanceID] = value;
return *this;
}
/**
* @brief Build and return the ConfidentialMPTMergeInbox wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
ConfidentialMPTMergeInbox
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return ConfidentialMPTMergeInbox{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -1,371 +0,0 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class ConfidentialMPTSendBuilder;
/**
* @brief Transaction: ConfidentialMPTSend
*
* Type: ttCONFIDENTIAL_MPT_SEND (88)
* Delegable: Delegation::delegable
* Amendment: featureConfidentialTransfer
* Privileges: noPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use ConfidentialMPTSendBuilder to construct new transactions.
*/
class ConfidentialMPTSend : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttCONFIDENTIAL_MPT_SEND;
/**
* @brief Construct a ConfidentialMPTSend transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit ConfidentialMPTSend(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTSend");
}
}
// Transaction-specific field getters
/**
* @brief Get sfMPTokenIssuanceID (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_UINT192::type::value_type
getMPTokenIssuanceID() const
{
return this->tx_->at(sfMPTokenIssuanceID);
}
/**
* @brief Get sfDestination (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_ACCOUNT::type::value_type
getDestination() const
{
return this->tx_->at(sfDestination);
}
/**
* @brief Get sfSenderEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getSenderEncryptedAmount() const
{
return this->tx_->at(sfSenderEncryptedAmount);
}
/**
* @brief Get sfDestinationEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getDestinationEncryptedAmount() const
{
return this->tx_->at(sfDestinationEncryptedAmount);
}
/**
* @brief Get sfIssuerEncryptedAmount (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getIssuerEncryptedAmount() const
{
return this->tx_->at(sfIssuerEncryptedAmount);
}
/**
* @brief Get sfAuditorEncryptedAmount (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getAuditorEncryptedAmount() const
{
if (hasAuditorEncryptedAmount())
{
return this->tx_->at(sfAuditorEncryptedAmount);
}
return std::nullopt;
}
/**
* @brief Check if sfAuditorEncryptedAmount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAuditorEncryptedAmount() const
{
return this->tx_->isFieldPresent(sfAuditorEncryptedAmount);
}
/**
* @brief Get sfZKProof (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getZKProof() const
{
return this->tx_->at(sfZKProof);
}
/**
* @brief Get sfAmountCommitment (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getAmountCommitment() const
{
return this->tx_->at(sfAmountCommitment);
}
/**
* @brief Get sfBalanceCommitment (soeREQUIRED)
* @return The field value.
*/
[[nodiscard]]
SF_VL::type::value_type
getBalanceCommitment() const
{
return this->tx_->at(sfBalanceCommitment);
}
/**
* @brief Get sfCredentialIDs (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VECTOR256::type::value_type>
getCredentialIDs() const
{
if (hasCredentialIDs())
{
return this->tx_->at(sfCredentialIDs);
}
return std::nullopt;
}
/**
* @brief Check if sfCredentialIDs is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasCredentialIDs() const
{
return this->tx_->isFieldPresent(sfCredentialIDs);
}
};
/**
* @brief Builder for ConfidentialMPTSend transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses Json::Value internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class ConfidentialMPTSendBuilder : public TransactionBuilderBase<ConfidentialMPTSendBuilder>
{
public:
/**
* @brief Construct a new ConfidentialMPTSendBuilder with required fields.
* @param account The account initiating the transaction.
* @param mPTokenIssuanceID The sfMPTokenIssuanceID field value.
* @param destination The sfDestination field value.
* @param senderEncryptedAmount The sfSenderEncryptedAmount field value.
* @param destinationEncryptedAmount The sfDestinationEncryptedAmount field value.
* @param issuerEncryptedAmount The sfIssuerEncryptedAmount field value.
* @param zKProof The sfZKProof field value.
* @param amountCommitment The sfAmountCommitment field value.
* @param balanceCommitment The sfBalanceCommitment field value.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
ConfidentialMPTSendBuilder(SF_ACCOUNT::type::value_type account,
std::decay_t<typename SF_UINT192::type::value_type> const& mPTokenIssuanceID, std::decay_t<typename SF_ACCOUNT::type::value_type> const& destination, std::decay_t<typename SF_VL::type::value_type> const& senderEncryptedAmount, std::decay_t<typename SF_VL::type::value_type> const& destinationEncryptedAmount, std::decay_t<typename SF_VL::type::value_type> const& issuerEncryptedAmount, std::decay_t<typename SF_VL::type::value_type> const& zKProof, std::decay_t<typename SF_VL::type::value_type> const& amountCommitment, std::decay_t<typename SF_VL::type::value_type> const& balanceCommitment, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<ConfidentialMPTSendBuilder>(ttCONFIDENTIAL_MPT_SEND, account, sequence, fee)
{
setMPTokenIssuanceID(mPTokenIssuanceID);
setDestination(destination);
setSenderEncryptedAmount(senderEncryptedAmount);
setDestinationEncryptedAmount(destinationEncryptedAmount);
setIssuerEncryptedAmount(issuerEncryptedAmount);
setZKProof(zKProof);
setAmountCommitment(amountCommitment);
setBalanceCommitment(balanceCommitment);
}
/**
* @brief Construct a ConfidentialMPTSendBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
ConfidentialMPTSendBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttCONFIDENTIAL_MPT_SEND)
{
throw std::runtime_error("Invalid transaction type for ConfidentialMPTSendBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfMPTokenIssuanceID (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setMPTokenIssuanceID(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfMPTokenIssuanceID] = value;
return *this;
}
/**
* @brief Set sfDestination (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setDestination(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfDestination] = value;
return *this;
}
/**
* @brief Set sfSenderEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setSenderEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfSenderEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfDestinationEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setDestinationEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfDestinationEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfIssuerEncryptedAmount (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setIssuerEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfIssuerEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfAuditorEncryptedAmount (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setAuditorEncryptedAmount(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAuditorEncryptedAmount] = value;
return *this;
}
/**
* @brief Set sfZKProof (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setZKProof(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfZKProof] = value;
return *this;
}
/**
* @brief Set sfAmountCommitment (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setAmountCommitment(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAmountCommitment] = value;
return *this;
}
/**
* @brief Set sfBalanceCommitment (soeREQUIRED)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setBalanceCommitment(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfBalanceCommitment] = value;
return *this;
}
/**
* @brief Set sfCredentialIDs (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
ConfidentialMPTSendBuilder&
setCredentialIDs(std::decay_t<typename SF_VECTOR256::type::value_type> const& value)
{
object_[sfCredentialIDs] = value;
return *this;
}
/**
* @brief Build and return the ConfidentialMPTSend wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
ConfidentialMPTSend
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return ConfidentialMPTSend{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -187,58 +187,6 @@ public:
{
return this->tx_->isFieldPresent(sfMutableFlags);
}
/**
* @brief Get sfIssuerEncryptionKey (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getIssuerEncryptionKey() const
{
if (hasIssuerEncryptionKey())
{
return this->tx_->at(sfIssuerEncryptionKey);
}
return std::nullopt;
}
/**
* @brief Check if sfIssuerEncryptionKey is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasIssuerEncryptionKey() const
{
return this->tx_->isFieldPresent(sfIssuerEncryptionKey);
}
/**
* @brief Get sfAuditorEncryptionKey (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_VL::type::value_type>
getAuditorEncryptionKey() const
{
if (hasAuditorEncryptionKey())
{
return this->tx_->at(sfAuditorEncryptionKey);
}
return std::nullopt;
}
/**
* @brief Check if sfAuditorEncryptionKey is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAuditorEncryptionKey() const
{
return this->tx_->isFieldPresent(sfAuditorEncryptionKey);
}
};
/**
@@ -349,28 +297,6 @@ public:
return *this;
}
/**
* @brief Set sfIssuerEncryptionKey (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenIssuanceSetBuilder&
setIssuerEncryptionKey(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfIssuerEncryptionKey] = value;
return *this;
}
/**
* @brief Set sfAuditorEncryptionKey (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
MPTokenIssuanceSetBuilder&
setAuditorEncryptionKey(std::decay_t<typename SF_VL::type::value_type> const& value)
{
object_[sfAuditorEncryptionKey] = value;
return *this;
}
/**
* @brief Build and return the MPTokenIssuanceSet wrapper.
* @param publicKey The public key for signing.

View File

@@ -122,7 +122,7 @@ private:
ApplyFlags flags_;
std::optional<ApplyViewImpl> view_;
// The ID of the batch transaction we are executing under, if set.
// The ID of the batch transaction we are executing under, if seated.
std::optional<uint256 const> parentBatchId_;
};

View File

@@ -162,6 +162,9 @@ public:
static NotTEC
checkSign(PreclaimContext const& ctx);
static NotTEC
checkBatchSign(PreclaimContext const& ctx);
// Returns the fee in fee units, not scaled for load.
static XRPAmount
calculateBaseFee(ReadView const& view, STTx const& tx);
@@ -290,7 +293,14 @@ protected:
std::optional<T> value,
unit::ValueUnit<Unit, T> min = unit::ValueUnit<Unit, T>{});
protected:
private:
std::pair<TER, XRPAmount>
reset(XRPAmount fee);
TER
consumeSeqProxy(SLE::pointer const& sleAccount);
TER
payFee();
static NotTEC
checkSingleSign(
ReadView const& view,
@@ -306,15 +316,6 @@ protected:
STObject const& sigObject,
beast::Journal const j);
private:
std::pair<TER, XRPAmount>
reset(XRPAmount fee);
TER
consumeSeqProxy(SLE::pointer const& sleAccount);
TER
payFee();
void trapTransaction(uint256) const;
/** Performs early sanity checks on the account and fee fields.

View File

@@ -398,8 +398,7 @@ using InvariantChecks = std::tuple<
ValidPseudoAccounts,
ValidLoanBroker,
ValidLoan,
ValidVault,
ValidConfidentialMPToken>;
ValidVault>;
/**
* @brief get a tuple of all invariant checks

View File

@@ -28,47 +28,4 @@ public:
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
};
/**
* @brief Invariants: Confidential MPToken consistency
*
* - Convert/ConvertBack symmetry:
* Regular MPToken balance change (±X) == COA (Confidential Outstanding Amount) change (∓X)
* - Cannot delete MPToken with non-zero confidential state:
* Cannot delete if sfIssuerEncryptedBalance exists
* Cannot delete if sfConfidentialBalanceInbox and sfConfidentialBalanceSpending exist
* - Privacy flag consistency:
* MPToken can only have encrypted fields if lsfMPTCanConfidentialAmount is set on
* issuance.
* - Encrypted field existence consistency:
* If sfConfidentialBalanceSpending/sfConfidentialBalanceInbox exists, then
* sfIssuerEncryptedBalance must also exist (and vice versa).
* - COA <= OutstandingAmount:
* Confidential outstanding balance cannot exceed total outstanding.
* - Verifies sfConfidentialBalanceVersion is changed whenever sfConfidentialBalanceSpending is
* modified on an MPToken.
*/
class ValidConfidentialMPToken
{
struct Changes
{
std::int64_t mptAmountDelta = 0;
std::int64_t coaDelta = 0;
std::int64_t outstandingDelta = 0;
SLE::const_pointer issuance;
bool deletedWithEncrypted = false;
bool badConsistency = false;
bool badCOA = false;
bool requiresPrivacyFlag = false;
bool badVersion = false;
};
std::map<uint192, Changes> changes_;
public:
void
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
};
} // namespace xrpl

View File

@@ -3,10 +3,10 @@
#include <xrpl/basics/Log.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/Quality.h>
#include <xrpl/tx/transactors/dex/AMMContext.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -2,7 +2,6 @@
#include <xrpl/basics/Log.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -14,6 +13,7 @@
#include <xrpl/tx/paths/detail/FlowDebugInfo.h>
#include <xrpl/tx/paths/detail/Steps.h>
#include <xrpl/tx/transactors/dex/AMMContext.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <boost/container/flat_set.hpp>
@@ -246,7 +246,7 @@ flow(
EitherAmount stepIn(*strand[0]->cachedIn());
for (auto i = 0; i < s; ++i)
{
bool valid = false;
bool valid;
std::tie(valid, stepIn) = strand[i]->validFwd(checkSB, checkAfView, stepIn);
if (!valid)
{

View File

@@ -1,8 +1,8 @@
#pragma once
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/nft.h>
#include <xrpl/tx/Transactor.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {

View File

@@ -1,12 +1,12 @@
#pragma once
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/nft.h>
#include <xrpl/tx/Transactor.h>
namespace xrpl {

View File

@@ -1,5 +1,7 @@
#pragma once
#include <xrpl/basics/Log.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/tx/Transactor.h>
namespace xrpl {
@@ -25,31 +27,29 @@ public:
static NotTEC
preflightSigValidated(PreflightContext const& ctx);
static NotTEC
checkBatchSign(PreclaimContext const& ctx);
static NotTEC
checkSign(PreclaimContext const& ctx);
TER
doApply() override;
static constexpr auto disabledTxTypes = std::to_array<TxType>(
{ttVAULT_CREATE,
ttVAULT_SET,
ttVAULT_DELETE,
ttVAULT_DEPOSIT,
ttVAULT_WITHDRAW,
ttVAULT_CLAWBACK,
ttLOAN_BROKER_SET,
ttLOAN_BROKER_DELETE,
ttLOAN_BROKER_COVER_DEPOSIT,
ttLOAN_BROKER_COVER_WITHDRAW,
ttLOAN_BROKER_COVER_CLAWBACK,
ttLOAN_SET,
ttLOAN_DELETE,
ttLOAN_MANAGE,
ttLOAN_PAY});
static constexpr auto disabledTxTypes = std::to_array<TxType>({
ttVAULT_CREATE,
ttVAULT_SET,
ttVAULT_DELETE,
ttVAULT_DEPOSIT,
ttVAULT_WITHDRAW,
ttVAULT_CLAWBACK,
ttLOAN_BROKER_SET,
ttLOAN_BROKER_DELETE,
ttLOAN_BROKER_COVER_DEPOSIT,
ttLOAN_BROKER_COVER_WITHDRAW,
ttLOAN_BROKER_COVER_CLAWBACK,
ttLOAN_SET,
ttLOAN_DELETE,
ttLOAN_MANAGE,
ttLOAN_PAY,
});
};
} // namespace xrpl

View File

@@ -1,42 +0,0 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
/**
* @brief Allows an MPT issuer to clawback confidential balances from a holder.
*
* This transaction enables the issuer of an MPToken Issuance (with clawback
* enabled) to reclaim confidential tokens from a holder's account. Unlike
* regular clawback, the issuer cannot see the holder's balance directly.
* Instead, the issuer must provide a zero-knowledge proof that demonstrates
* they know the exact encrypted balance amount.
*
* @par Cryptographic Operations:
* - **Equality Proof Verification**: Verifies that the issuer's revealed
* amount matches the holder's encrypted balance using the issuer's
* ElGamal private key.
*
* @see ConfidentialMPTSend, ConfidentialMPTConvert
*/
class ConfidentialMPTClawback : public Transactor
{
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit ConfidentialMPTClawback(ApplyContext& ctx) : Transactor(ctx)
{
}
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
};
} // namespace xrpl

View File

@@ -1,44 +0,0 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
/**
* @brief Converts public (plaintext) MPT balance to confidential (encrypted)
* balance.
*
* This transaction allows a token holder to convert their publicly visible
* MPToken balance into an encrypted confidential balance. Once converted,
* the balance can only be spent using ConfidentialMPTSend transactions and
* remains hidden from public view on the ledger.
*
* @par Cryptographic Operations:
* - **Schnorr Proof Verification**: When registering a new ElGamal public key,
* verifies proof of knowledge of the corresponding private key.
* - **Revealed Amount Verification**: Verifies that the provided encrypted
* amounts (for holder, issuer, and optionally auditor) all encrypt the
* same plaintext amount using the provided blinding factor.
*
* @see ConfidentialMPTConvertBack, ConfidentialMPTSend
*/
class ConfidentialMPTConvert : public Transactor
{
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit ConfidentialMPTConvert(ApplyContext& ctx) : Transactor(ctx)
{
}
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
};
} // namespace xrpl

View File

@@ -1,45 +0,0 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
/**
* @brief Converts confidential (encrypted) MPT balance back to public
* (plaintext) balance.
*
* This transaction allows a token holder to convert their encrypted
* confidential balance back into a publicly visible MPToken balance. The
* holder must prove they have sufficient confidential balance without
* revealing the actual balance amount.
*
* @par Cryptographic Operations:
* - **Revealed Amount Verification**: Verifies that the provided encrypted
* amounts correctly encrypt the conversion amount.
* - **Pedersen Linkage Proof**: Verifies that the provided balance commitment
* correctly links to the holder's encrypted spending balance.
* - **Bulletproof Range Proof**: Verifies that the remaining balance (after
* conversion) is non-negative, ensuring the holder has sufficient funds.
*
* @see ConfidentialMPTConvert, ConfidentialMPTSend
*/
class ConfidentialMPTConvertBack : public Transactor
{
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit ConfidentialMPTConvertBack(ApplyContext& ctx) : Transactor(ctx)
{
}
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
};
} // namespace xrpl

View File

@@ -1,46 +0,0 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
/**
* @brief Merges the confidential inbox balance into the spending balance.
*
* In the confidential transfer system, incoming funds are deposited into an
* "inbox" balance that the recipient cannot immediately spend. This prevents
* front-running attacks where an attacker could invalidate a pending
* transaction by sending funds to the sender. This transaction merges the
* inbox into the spending balance, making those funds available for spending.
*
* @par Cryptographic Operations:
* - **Homomorphic Addition**: Adds the encrypted inbox balance to the
* encrypted spending balance using ElGamal homomorphic properties.
* - **Zero Encryption**: Resets the inbox to an encryption of zero.
*
* @note This transaction requires no zero-knowledge proofs because it only
* combines encrypted values that the holder already owns. The
* homomorphic properties of ElGamal encryption ensure correctness.
*
* @see ConfidentialMPTSend, ConfidentialMPTConvert
*/
class ConfidentialMPTMergeInbox : public Transactor
{
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit ConfidentialMPTMergeInbox(ApplyContext& ctx) : Transactor(ctx)
{
}
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
};
} // namespace xrpl

View File

@@ -1,55 +0,0 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
/**
* @brief Transfers confidential MPT tokens between holders privately.
*
* This transaction enables private token transfers where the transfer amount
* is hidden from public view. Both sender and recipient must have initialized
* confidential balances. The transaction provides encrypted amounts for all
* parties (sender, destination, issuer, and optionally auditor) along with
* zero-knowledge proofs that verify correctness without revealing the amount.
*
* @par Cryptographic Operations:
* - **Multi-Ciphertext Equality Proof**: Verifies that all encrypted amounts
* (sender, destination, issuer, auditor) encrypt the same plaintext value.
* - **Amount Pedersen Linkage Proof**: Verifies that the amount commitment
* correctly links to the sender's encrypted amount.
* - **Balance Pedersen Linkage Proof**: Verifies that the balance commitment
* correctly links to the sender's encrypted spending balance.
* - **Bulletproof Range Proof**: Verifies remaining balance and
* transfer amount are non-negative.
*
* @note Funds are deposited into the destination's inbox, not spending
* balance. The recipient must call ConfidentialMPTMergeInbox to make
* received funds spendable.
*
* @see ConfidentialMPTMergeInbox, ConfidentialMPTConvert,
* ConfidentialMPTConvertBack
*/
class ConfidentialMPTSend : public Transactor
{
/// Size of two Pedersen linkage proofs (amount + balance)
static constexpr std::size_t doublePedersenProofLength = 2 * ecPedersenProofLength;
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit ConfidentialMPTSend(ApplyContext& ctx) : Transactor(ctx)
{
}
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
};
} // namespace xrpl

View File

@@ -31,6 +31,13 @@ public:
static TER
preclaim(PreclaimContext const& ctx);
static TER
createMPToken(
ApplyView& view,
MPTID const& mptIssuanceID,
AccountID const& account,
std::uint32_t const flags);
TER
doApply() override;
};

View File

@@ -59,8 +59,7 @@ Logs::File::open(boost::filesystem::path const& path)
bool wasOpened = false;
// VFALCO TODO Make this work with Unicode file paths
std::unique_ptr<std::ofstream> stream =
std::make_unique<std::ofstream>(path.c_str(), std::fstream::app);
std::unique_ptr<std::ofstream> stream(new std::ofstream(path.c_str(), std::fstream::app));
if (stream->good())
{

View File

@@ -185,7 +185,7 @@ OpenView::txsEnd() const -> std::unique_ptr<txs_type::iter_base>
bool
OpenView::txExists(key_type const& key) const
{
return txs_.contains(key) || base_->txExists(key);
return txs_.contains(key);
}
auto

View File

@@ -139,9 +139,7 @@ authorizeMPToken(
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto const sleMpt = view.peek(mptokenKey);
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0 ||
(view.rules().enabled(fixSecurity3_1_3) &&
(*sleMpt)[~sfLockedAmount].value_or(0) != 0))
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0)
return tecINTERNAL; // LCOV_EXCL_LINE
if (!view.dirRemove(
@@ -254,17 +252,9 @@ removeEmptyHolding(
// balance, it can not just be deleted, because that will throw the issuance
// accounting out of balance, so fail. Since this should be impossible
// anyway, I'm not going to put any effort into it.
if (mptoken->at(sfMPTAmount) != 0 ||
(view.rules().enabled(fixSecurity3_1_3) && (*mptoken)[~sfLockedAmount].value_or(0) != 0))
if (mptoken->at(sfMPTAmount) != 0)
return tecHAS_OBLIGATIONS;
// Don't delete if the token still has confidential balances
if (mptoken->isFieldPresent(sfConfidentialBalanceInbox) ||
mptoken->isFieldPresent(sfConfidentialBalanceSpending))
{
return tecHAS_OBLIGATIONS;
}
return authorizeMPToken(
view,
{}, // priorBalance
@@ -759,30 +749,4 @@ rippleUnlockEscrowMPT(
return tesSUCCESS;
}
TER
createMPToken(
ApplyView& view,
MPTID const& mptIssuanceID,
AccountID const& account,
std::uint32_t const flags)
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto const ownerNode =
view.dirInsert(keylet::ownerDir(account), mptokenKey, describeOwnerDir(account));
if (!ownerNode)
return tecDIR_FULL; // LCOV_EXCL_LINE
auto mptoken = std::make_shared<SLE>(mptokenKey);
(*mptoken)[sfAccount] = account;
(*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
(*mptoken)[sfFlags] = flags;
(*mptoken)[sfOwnerNode] = *ownerNode;
view.insert(mptoken);
return tesSUCCESS;
}
} // namespace xrpl

View File

@@ -334,8 +334,7 @@ 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))
{
if (auto const err = requireAuth(view, mptIssue, account, AuthType::StrongAuth);
!isTesSuccess(err))

View File

@@ -23,7 +23,7 @@ namespace {
// and follow the format described at http://semver.org/
//------------------------------------------------------------------------------
// clang-format off
char const* const versionString = "3.2.0-b0"
char const* const versionString = "3.2.0-b3"
// clang-format on
;

View File

@@ -1,445 +0,0 @@
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Protocol.h>
#include <openssl/rand.h>
#include <utility/mpt_utility.h>
namespace xrpl {
/**
* @brief Converts an XRPL AccountID to mpt-crypto lib C struct.
*
* @param account The AccountID.
* @return The equivalent mpt-crypto lib account_id struct.
*/
account_id
toAccountId(AccountID const& account)
{
account_id res;
std::memcpy(res.bytes, account.data(), kMPT_ACCOUNT_ID_SIZE);
return res;
}
/**
* @brief Converts an XRPL uint192 to mpt-crypto lib C struct.
*
* @param i The XRPL MPTokenIssuance ID.
* @return The equivalent mpt-crypto lib mpt_issuance_id struct.
*/
mpt_issuance_id
toIssuanceId(uint192 const& issuance)
{
mpt_issuance_id res;
std::memcpy(res.bytes, issuance.data(), kMPT_ISSUANCE_ID_SIZE);
return res;
}
uint256
getSendContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
AccountID const& destination,
std::uint32_t version)
{
uint256 result;
mpt_get_send_context_hash(
toAccountId(account),
toIssuanceId(issuanceID),
sequence,
toAccountId(destination),
version,
result.data());
return result;
}
uint256
getClawbackContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
AccountID const& holder)
{
uint256 result;
mpt_get_clawback_context_hash(
toAccountId(account),
toIssuanceId(issuanceID),
sequence,
toAccountId(holder),
result.data());
return result;
}
uint256
getConvertContextHash(AccountID const& account, uint192 const& issuanceID, std::uint32_t sequence)
{
uint256 result;
mpt_get_convert_context_hash(
toAccountId(account), toIssuanceId(issuanceID), sequence, result.data());
return result;
}
uint256
getConvertBackContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
std::uint32_t version)
{
uint256 result;
mpt_get_convert_back_context_hash(
toAccountId(account), toIssuanceId(issuanceID), sequence, version, result.data());
return result;
}
std::optional<EcPair>
makeEcPair(Slice const& buffer)
{
if (buffer.length() != 2 * ecGamalEncryptedLength)
return std::nullopt; // LCOV_EXCL_LINE
auto parsePubKey = [](Slice const& slice, secp256k1_pubkey& out) {
return secp256k1_ec_pubkey_parse(
secp256k1Context(),
&out,
reinterpret_cast<unsigned char const*>(slice.data()),
slice.length());
};
Slice const s1{buffer.data(), ecGamalEncryptedLength};
Slice const s2{buffer.data() + ecGamalEncryptedLength, ecGamalEncryptedLength};
EcPair pair{};
if (parsePubKey(s1, pair.c1) != 1 || parsePubKey(s2, pair.c2) != 1)
return std::nullopt;
return pair;
}
std::optional<Buffer>
serializeEcPair(EcPair const& pair)
{
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);
return ret == 1 && outLen == ecGamalEncryptedLength;
};
Buffer buffer(ecGamalEncryptedTotalLength);
unsigned char* ptr = buffer.data();
bool const res1 = serializePubKey(pair.c1, ptr);
bool const res2 = serializePubKey(pair.c2, ptr + ecGamalEncryptedLength);
if (!res1 || !res2)
return std::nullopt;
return buffer;
}
bool
isValidCiphertext(Slice const& buffer)
{
return makeEcPair(buffer).has_value();
}
bool
isValidCompressedECPoint(Slice const& buffer)
{
if (buffer.size() != compressedECPointLength)
return false;
// Compressed EC points must start with 0x02 or 0x03
if (buffer[0] != ecCompressedPrefixEvenY && buffer[0] != ecCompressedPrefixOddY)
return false;
secp256k1_pubkey point;
return secp256k1_ec_pubkey_parse(secp256k1Context(), &point, buffer.data(), buffer.size()) == 1;
}
std::optional<Buffer>
homomorphicAdd(Slice const& a, Slice const& b)
{
if (a.length() != ecGamalEncryptedTotalLength || b.length() != ecGamalEncryptedTotalLength)
return std::nullopt;
auto const pairA = makeEcPair(a);
auto const pairB = makeEcPair(b);
if (!pairA || !pairB)
return std::nullopt;
EcPair sum{};
if (auto res = secp256k1_elgamal_add(
secp256k1Context(), &sum.c1, &sum.c2, &pairA->c1, &pairA->c2, &pairB->c1, &pairB->c2);
res != 1)
{
return std::nullopt;
}
return serializeEcPair(sum);
}
std::optional<Buffer>
homomorphicSubtract(Slice const& a, Slice const& b)
{
if (a.length() != ecGamalEncryptedTotalLength || b.length() != ecGamalEncryptedTotalLength)
return std::nullopt;
auto const pairA = makeEcPair(a);
auto const pairB = makeEcPair(b);
if (!pairA || !pairB)
return std::nullopt;
EcPair diff{};
if (auto res = secp256k1_elgamal_subtract(
secp256k1Context(), &diff.c1, &diff.c2, &pairA->c1, &pairA->c2, &pairB->c1, &pairB->c2);
res != 1)
{
return std::nullopt;
}
return serializeEcPair(diff);
}
Buffer
generateBlindingFactor()
{
unsigned char blindingFactor[ecBlindingFactorLength];
// todo: might need to be updated using another RNG
if (RAND_bytes(blindingFactor, ecBlindingFactorLength) != 1)
Throw<std::runtime_error>("Failed to generate random number");
return Buffer(blindingFactor, ecBlindingFactorLength);
}
std::optional<Buffer>
encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindingFactor)
{
if (blindingFactor.size() != ecBlindingFactorLength || pubKeySlice.size() != ecPubKeyLength)
return std::nullopt;
Buffer out(ecGamalEncryptedTotalLength);
if (mpt_encrypt_amount(amt, pubKeySlice.data(), blindingFactor.data(), out.data()) != 0)
return std::nullopt;
return out;
}
std::optional<Buffer>
encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, MPTID const& mptId)
{
if (pubKeySlice.size() != ecPubKeyLength)
return std::nullopt; // LCOV_EXCL_LINE
EcPair pair{};
secp256k1_pubkey pubKey;
if (auto res = secp256k1_ec_pubkey_parse(
secp256k1Context(), &pubKey, pubKeySlice.data(), ecPubKeyLength);
res != 1)
{
return std::nullopt; // LCOV_EXCL_LINE
}
if (auto res = generate_canonical_encrypted_zero(
secp256k1Context(), &pair.c1, &pair.c2, &pubKey, account.data(), mptId.data());
res != 1)
{
return std::nullopt; // LCOV_EXCL_LINE
}
return serializeEcPair(pair);
}
TER
verifyRevealedAmount(
uint64_t const amount,
Slice const& blindingFactor,
ConfidentialRecipient const& holder,
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor)
{
if (blindingFactor.size() != ecBlindingFactorLength ||
holder.publicKey.size() != ecPubKeyLength ||
holder.encryptedAmount.size() != ecGamalEncryptedTotalLength ||
issuer.publicKey.size() != ecPubKeyLength ||
issuer.encryptedAmount.size() != ecGamalEncryptedTotalLength)
return tecINTERNAL; // LCOV_EXCL_LINE
auto toParticipant = [](ConfidentialRecipient const& r) {
mpt_confidential_participant p;
std::memcpy(p.pubkey, r.publicKey.data(), kMPT_PUBKEY_SIZE);
std::memcpy(p.ciphertext, r.encryptedAmount.data(), kMPT_ELGAMAL_TOTAL_SIZE);
return p;
};
auto const holderP = toParticipant(holder);
auto const issuerP = toParticipant(issuer);
mpt_confidential_participant auditorP;
mpt_confidential_participant const* auditorPtr = nullptr;
if (auditor)
{
if (auditor->publicKey.size() != ecPubKeyLength ||
auditor->encryptedAmount.size() != ecGamalEncryptedTotalLength)
return tecINTERNAL; // LCOV_EXCL_LINE
auditorP = toParticipant(*auditor);
auditorPtr = &auditorP;
}
if (mpt_verify_revealed_amount(amount, blindingFactor.data(), &holderP, &issuerP, auditorPtr) !=
0)
return tecBAD_PROOF;
return tesSUCCESS;
}
NotTEC
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))
return temMALFORMED; // LCOV_EXCL_LINE
if (object[sfHolderEncryptedAmount].length() != ecGamalEncryptedTotalLength ||
object[sfIssuerEncryptedAmount].length() != ecGamalEncryptedTotalLength)
return temBAD_CIPHERTEXT;
bool const hasAuditor = object.isFieldPresent(sfAuditorEncryptedAmount);
if (hasAuditor && object[sfAuditorEncryptedAmount].length() != ecGamalEncryptedTotalLength)
return temBAD_CIPHERTEXT;
if (!isValidCiphertext(object[sfHolderEncryptedAmount]) ||
!isValidCiphertext(object[sfIssuerEncryptedAmount]))
return temBAD_CIPHERTEXT;
if (hasAuditor && !isValidCiphertext(object[sfAuditorEncryptedAmount]))
return temBAD_CIPHERTEXT;
return tesSUCCESS;
}
TER
verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 const& contextHash)
{
if (proofSlice.size() != ecSchnorrProofLength || pubKeySlice.size() != ecPubKeyLength)
return tecINTERNAL; // LCOV_EXCL_LINE
if (mpt_verify_convert_proof(proofSlice.data(), pubKeySlice.data(), contextHash.data()) != 0)
return tecBAD_PROOF;
return tesSUCCESS;
}
TER
verifyClawbackEqualityProof(
uint64_t const amount,
Slice const& proof,
Slice const& pubKeySlice,
Slice const& ciphertext,
uint256 const& contextHash)
{
if (ciphertext.size() != ecGamalEncryptedTotalLength || pubKeySlice.size() != ecPubKeyLength ||
proof.size() != ecEqualityProofLength)
return tecINTERNAL; // LCOV_EXCL_LINE
if (mpt_verify_clawback_proof(
proof.data(), amount, pubKeySlice.data(), ciphertext.data(), contextHash.data()) != 0)
return tecBAD_PROOF;
return tesSUCCESS;
}
TER
verifySendProof(
Slice const& proof,
ConfidentialRecipient const& sender,
ConfidentialRecipient const& destination,
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor,
Slice const& spendingBalance,
Slice const& amountCommitment,
Slice const& balanceCommitment,
uint256 const& contextHash)
{
auto const recipientCount = getConfidentialRecipientCount(auditor.has_value());
auto const expectedProofSize = getEqualityProofSize(recipientCount) +
2 * ecPedersenProofLength + ecDoubleBulletproofLength;
if (proof.size() != expectedProofSize || sender.publicKey.size() != ecPubKeyLength ||
sender.encryptedAmount.size() != ecGamalEncryptedTotalLength ||
destination.publicKey.size() != ecPubKeyLength ||
destination.encryptedAmount.size() != ecGamalEncryptedTotalLength ||
issuer.publicKey.size() != ecPubKeyLength ||
issuer.encryptedAmount.size() != ecGamalEncryptedTotalLength ||
spendingBalance.size() != ecGamalEncryptedTotalLength ||
amountCommitment.size() != ecPedersenCommitmentLength ||
balanceCommitment.size() != ecPedersenCommitmentLength)
return tecINTERNAL; // LCOV_EXCL_LINE
auto makeParticipant = [](ConfidentialRecipient const& r) {
mpt_confidential_participant p;
std::memcpy(p.pubkey, r.publicKey.data(), kMPT_PUBKEY_SIZE);
std::memcpy(p.ciphertext, r.encryptedAmount.data(), kMPT_ELGAMAL_TOTAL_SIZE);
return p;
};
std::vector<mpt_confidential_participant> participants(recipientCount);
participants[0] = makeParticipant(sender);
participants[1] = makeParticipant(destination);
participants[2] = makeParticipant(issuer);
if (auditor)
{
if (auditor->publicKey.size() != ecPubKeyLength ||
auditor->encryptedAmount.size() != ecGamalEncryptedTotalLength)
return tecINTERNAL;
participants[3] = makeParticipant(*auditor);
}
if (mpt_verify_send_proof(
proof.data(),
proof.size(),
participants.data(),
static_cast<uint8_t>(recipientCount),
spendingBalance.data(),
amountCommitment.data(),
balanceCommitment.data(),
contextHash.data()) != 0)
return tecBAD_PROOF;
return tesSUCCESS;
}
TER
verifyConvertBackProof(
Slice const& proof,
Slice const& pubKeySlice,
Slice const& spendingBalance,
Slice const& balanceCommitment,
uint64_t amount,
uint256 const& contextHash)
{
if (proof.size() != ecPedersenProofLength + ecSingleBulletproofLength ||
pubKeySlice.size() != ecPubKeyLength ||
spendingBalance.size() != ecGamalEncryptedTotalLength ||
balanceCommitment.size() != ecPedersenCommitmentLength)
return tecINTERNAL; // LCOV_EXCL_LINE
if (mpt_verify_convert_back_proof(
proof.data(),
pubKeySlice.data(),
spendingBalance.data(),
balanceCommitment.data(),
amount,
contextHash.data()) != 0)
return tecBAD_PROOF;
return tesSUCCESS;
}
} // namespace xrpl

View File

@@ -3,7 +3,6 @@
#include <xrpl/basics/contract.h>
#include <xrpl/basics/strHex.h>
#include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/detail/secp256k1.h>
@@ -209,7 +208,7 @@ publicKeyType(Slice const& slice)
if (slice[0] == 0xED)
return KeyType::ed25519;
if (slice[0] == ecCompressedPrefixEvenY || slice[0] == ecCompressedPrefixOddY)
if (slice[0] == 0x02 || slice[0] == 0x03)
return KeyType::secp256k1;
}

View File

@@ -73,7 +73,6 @@ STTx::STTx(STObject&& object) : STObject(std::move(object))
tx_type_ = safe_cast<TxType>(getFieldU16(sfTransactionType));
applyTemplate(getTxFormat(tx_type_)->getSOTemplate()); // may throw
tid_ = getHash(HashPrefix::transactionID);
buildBatchTxnIds();
}
STTx::STTx(SerialIter& sit) : STObject(sfTransaction)
@@ -90,7 +89,6 @@ STTx::STTx(SerialIter& sit) : STObject(sfTransaction)
applyTemplate(getTxFormat(tx_type_)->getSOTemplate()); // May throw
tid_ = getHash(HashPrefix::transactionID);
buildBatchTxnIds();
}
STTx::STTx(TxType type, std::function<void(STObject&)> assembler) : STObject(sfTransaction)
@@ -108,7 +106,6 @@ STTx::STTx(TxType type, std::function<void(STObject&)> assembler) : STObject(sfT
LogicError("Transaction type was mutated during assembly");
tid_ = getHash(HashPrefix::transactionID);
buildBatchTxnIds();
}
STBase*
@@ -297,8 +294,6 @@ STTx::checkBatchSign(Rules const& rules) const
JLOG(debugLog().fatal()) << "not a batch transaction";
return Unexpected("Not a batch transaction.");
}
if (!isFieldPresent(sfBatchSigners))
return Unexpected("Missing BatchSigners field.");
STArray const& signers{getFieldArray(sfBatchSigners)};
for (auto const& signer : signers)
{
@@ -313,8 +308,9 @@ STTx::checkBatchSign(Rules const& rules) const
}
catch (std::exception const& e)
{
return Unexpected(std::string("Internal batch signature check failure: ") + e.what());
JLOG(debugLog().error()) << "Batch signature check failed: " << e.what();
}
return Unexpected("Internal batch signature check failure.");
}
Json::Value
@@ -436,7 +432,6 @@ STTx::checkBatchSingleSign(STObject const& batchSigner) const
{
Serializer msg;
serializeBatch(msg, getFlags(), getBatchTransactionIDs());
finishMultiSigningData(batchSigner.getAccountID(sfAccount), msg);
return singleSignHelper(batchSigner, msg.slice());
}
@@ -510,7 +505,7 @@ multiSignHelper(
{
return Unexpected(
std::string("Invalid signature on account ") + toBase58(accountID) +
(errorWhat ? ": " + *errorWhat : "") + ".");
errorWhat.value_or("") + ".");
}
}
// All signatures verified.
@@ -559,24 +554,41 @@ STTx::checkMultiSign(Rules const& rules, STObject const& sigObject) const
rules);
}
void
STTx::buildBatchTxnIds()
{
if (tx_type_ != ttBATCH || !isFieldPresent(sfRawTransactions))
return;
auto const& raw = getFieldArray(sfRawTransactions);
batchTxnIds_.reserve(raw.size());
for (STObject const& rb : raw)
batchTxnIds_.push_back(rb.getHash(HashPrefix::transactionID));
}
/**
* @brief Retrieves a batch of transaction IDs from the STTx.
*
* This function returns a vector of transaction IDs by extracting them from
* the field array `sfRawTransactions` within the STTx. If the batch
* transaction IDs have already been computed and cached in `batchTxnIds_`,
* it returns the cached vector. Otherwise, it computes the transaction IDs,
* caches them, and then returns the vector.
*
* @return A vector of `uint256` containing the batch transaction IDs.
*
* @note The function asserts that the `sfRawTransactions` field array is not
* empty and that the size of the computed batch transaction IDs matches the
* size of the `sfRawTransactions` field array.
*/
std::vector<uint256> const&
STTx::getBatchTransactionIDs() const
{
XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::getBatchTransactionIDs : not a batch transaction");
XRPL_ASSERT(
!batchTxnIds_.empty(), "STTx::getBatchTransactionIDs : batch transaction IDs not built");
!getFieldArray(sfRawTransactions).empty(),
"STTx::getBatchTransactionIDs : empty raw transactions");
// The list of inner ids is built once, then reused on subsequent calls.
// After the list is built, it must always have the same size as the array
// `sfRawTransactions`. The assert below verifies that.
if (batchTxnIds_.empty())
{
for (STObject const& rb : getFieldArray(sfRawTransactions))
batchTxnIds_.push_back(rb.getHash(HashPrefix::transactionID));
}
XRPL_ASSERT(
batchTxnIds_.size() == getFieldArray(sfRawTransactions).size(),
"STTx::getBatchTransactionIDs : batch transaction IDs size mismatch");
return batchTxnIds_;
}
@@ -744,9 +756,6 @@ isRawTransactionOkay(STObject const& st, std::string& reason)
}
raw.applyTemplate(getTxFormat(tt)->getSOTemplate());
if (!passesLocalChecks(raw, reason))
return false;
}
catch (std::exception const& e)
{

View File

@@ -106,7 +106,6 @@ transResults()
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."),
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
MAKE_ERROR(tecBAD_PROOF, "Proof cannot be verified"),
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
@@ -199,7 +198,6 @@ transResults()
MAKE_ERROR(temARRAY_TOO_LARGE, "Malformed: Array is too large."),
MAKE_ERROR(temBAD_TRANSFER_FEE, "Malformed: Transfer fee is outside valid range."),
MAKE_ERROR(temINVALID_INNER_BATCH, "Malformed: Invalid inner batch transaction."),
MAKE_ERROR(temBAD_CIPHERTEXT, "Malformed: Invalid ciphertext."),
MAKE_ERROR(terRETRY, "Retry transaction."),
MAKE_ERROR(terFUNDS_SPENT, "DEPRECATED."),

View File

@@ -4,8 +4,6 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DelegateHelpers.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -18,6 +16,8 @@
#include <xrpl/tx/SignerEntries.h>
#include <xrpl/tx/Transactor.h>
#include <xrpl/tx/apply.h>
#include <xrpl/tx/transactors/delegate/DelegateUtils.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {
@@ -177,15 +177,13 @@ Transactor::preflight1(PreflightContext const& ctx, std::uint32_t flagMask)
if (ctx.tx.getSeqProxy().isTicket() && ctx.tx.isFieldPresent(sfAccountTxnID))
return temINVALID;
if (ctx.tx.isFlag(tfInnerBatchTxn) && !ctx.rules.enabled(featureBatchV1_1))
if (ctx.tx.isFlag(tfInnerBatchTxn) && !ctx.rules.enabled(featureBatch))
return temINVALID_FLAG;
// Reject if the inner batch flag and parentBatchId are inconsistent.
// A standalone tx with tfInnerBatchTxn but no parentBatchId is an
// attack attempt. A tx with parentBatchId but without tfInnerBatchTxn
// is a programming error.
if (ctx.tx.isFlag(tfInnerBatchTxn) != ctx.parentBatchId.has_value())
return temINVALID_INNER_BATCH;
XRPL_ASSERT(
ctx.tx.isFlag(tfInnerBatchTxn) == ctx.parentBatchId.has_value() ||
!ctx.rules.enabled(featureBatch),
"Inner batch transaction must have a parent batch ID.");
return tesSUCCESS;
}
@@ -201,18 +199,15 @@ Transactor::preflight2(PreflightContext const& ctx)
return *ret;
}
// Skip signature check on batch inner transactions, but only if
// this tx was actually submitted through the batch apply path
// (parentBatchId is set). Without this check, a standalone tx
// with tfInnerBatchTxn could bypass signature verification.
if (ctx.tx.isFlag(tfInnerBatchTxn))
{
if (!ctx.rules.enabled(featureBatchV1_1))
return temINVALID_FLAG;
if (!ctx.parentBatchId.has_value())
return temINVALID_INNER_BATCH;
// It should be impossible for the InnerBatchTxn flag to be set without
// featureBatch being enabled
XRPL_ASSERT_PARTS(
!ctx.tx.isFlag(tfInnerBatchTxn) || ctx.rules.enabled(featureBatch),
"xrpl::Transactor::preflight2",
"InnerBatch flag only set if feature enabled");
// Skip signature check on batch inner transactions
if (ctx.tx.isFlag(tfInnerBatchTxn) && ctx.rules.enabled(featureBatch))
return tesSUCCESS;
}
// Do not add any checks after this point that are relevant for
// batch inner transactions. They will be skipped.
@@ -368,13 +363,6 @@ Transactor::checkFee(PreclaimContext const& ctx, XRPAmount baseFee)
auto const balance = (*sle)[sfBalance].xrp();
// NOTE: Because preclaim evaluates against a static readview, it
// does not reflect fee deductions from other transactions paid by
// the same account within the current ledger.
// As a result, if an account's balance is over-committed across multiple
// transactions, this check may pass optimistically.
// The fee shortfall will be handled by the Transactor::reset mechanism,
// which caps the fee to the remaining actual balance.
if (balance < feePaid)
{
JLOG(ctx.j.trace()) << "Insufficient balance:" << " balance=" << to_string(balance)
@@ -653,7 +641,7 @@ Transactor::checkSign(
auto const pkSigner = sigObject.getFieldVL(sfSigningPubKey);
// Ignore signature check on batch inner transactions
if (parentBatchId && view.rules().enabled(featureBatchV1_1))
if (parentBatchId && view.rules().enabled(featureBatch))
{
// Defensive Check: These values are also checked in Batch::preflight
if (sigObject.isFieldPresent(sfTxnSignature) || !pkSigner.empty() ||
@@ -704,6 +692,50 @@ Transactor::checkSign(PreclaimContext const& ctx)
return checkSign(ctx.view, ctx.flags, ctx.parentBatchId, idAccount, ctx.tx, ctx.j);
}
NotTEC
Transactor::checkBatchSign(PreclaimContext const& ctx)
{
NotTEC ret = tesSUCCESS;
STArray const& signers{ctx.tx.getFieldArray(sfBatchSigners)};
for (auto const& signer : signers)
{
auto const idAccount = signer.getAccountID(sfAccount);
Blob const& pkSigner = signer.getFieldVL(sfSigningPubKey);
if (pkSigner.empty())
{
if (ret = checkMultiSign(ctx.view, ctx.flags, idAccount, signer, ctx.j);
!isTesSuccess(ret))
return ret;
}
else
{
// LCOV_EXCL_START
if (!publicKeyType(makeSlice(pkSigner)))
return tefBAD_AUTH;
// LCOV_EXCL_STOP
auto const idSigner = calcAccountID(PublicKey(makeSlice(pkSigner)));
auto const sleAccount = ctx.view.read(keylet::account(idAccount));
// A batch can include transactions from an un-created account ONLY
// when the account master key is the signer
if (!sleAccount)
{
if (idAccount != idSigner)
return tefBAD_AUTH;
return tesSUCCESS;
}
if (ret = checkSingleSign(ctx.view, idSigner, idAccount, sleAccount, ctx.j);
!isTesSuccess(ret))
return ret;
}
}
return ret;
}
NotTEC
Transactor::checkSingleSign(
ReadView const& view,
@@ -992,7 +1024,7 @@ Transactor::reset(XRPAmount fee)
// balance should have already been checked in checkFee / preFlight.
XRPL_ASSERT(
(fee == beast::zero || balance != beast::zero) && (!view().open() || balance >= fee),
balance != beast::zero && (!view().open() || balance >= fee),
"xrpl::Transactor::reset : valid balance");
// We retry/reject the transaction if the account balance is zero or

View File

@@ -24,12 +24,29 @@ checkValidity(HashRouter& router, STTx const& tx, Rules const& rules)
auto const flags = router.getFlags(id);
// Ignore signature check on batch inner transactions
if (tx.isFlag(tfInnerBatchTxn) && rules.enabled(featureBatchV1_1))
if (tx.isFlag(tfInnerBatchTxn) && rules.enabled(featureBatch))
{
// Defensive Check: These values are also checked in Batch::preflight
if (tx.isFieldPresent(sfTxnSignature) || !tx.getSigningPubKey().empty() ||
tx.isFieldPresent(sfSigners))
return {Validity::SigBad, "Malformed: Invalid inner batch transaction."};
// This block should probably have never been included in the
// original `Batch` implementation. An inner transaction never
// has a valid signature.
bool const neverValid = rules.enabled(fixBatchInnerSigs);
if (!neverValid)
{
std::string reason;
if (!passesLocalChecks(tx, reason))
{
router.setFlags(id, SF_LOCALBAD);
return {Validity::SigGoodOnly, reason};
}
router.setFlags(id, SF_SIGGOOD);
return {Validity::Valid, ""};
}
}
if (any(flags & SF_SIGBAD))

View File

@@ -2,9 +2,9 @@
//
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -175,32 +175,18 @@ ValidLoanBroker::finalize(
return false;
}
auto const& vaultAsset = vault->at(sfAsset);
auto const pseudoBalance = accountHolds(
view,
after->at(sfAccount),
vaultAsset,
FreezeHandling::fhIGNORE_FREEZE,
AuthHandling::ahIGNORE_AUTH,
j);
if (after->at(sfCoverAvailable) < pseudoBalance)
if (after->at(sfCoverAvailable) < accountHolds(
view,
after->at(sfAccount),
vaultAsset,
FreezeHandling::fhIGNORE_FREEZE,
AuthHandling::ahIGNORE_AUTH,
j))
{
JLOG(j.fatal()) << "Invariant failed: Loan Broker cover available "
"is less than pseudo-account asset balance";
return false;
}
if (view.rules().enabled(fixSecurity3_1_3))
{
// Don't check the balance when LoanBroker is deleted,
// sfCoverAvailable is not zeroed
if (tx.getTxnType() != ttLOAN_BROKER_DELETE &&
after->at(sfCoverAvailable) > pseudoBalance)
{
JLOG(j.fatal()) << "Invariant failed: Loan Broker cover available is greater "
"than pseudo-account asset balance";
return false;
}
}
}
return true;
}

View File

@@ -194,208 +194,4 @@ ValidMPTIssuance::finalize(
mptokensDeleted_ == 0;
}
void
ValidConfidentialMPToken::visitEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)
{
// Helper to get MPToken Issuance ID safely
auto const getMptID = [](std::shared_ptr<SLE const> const& sle) -> uint192 {
if (!sle)
return beast::zero;
if (sle->getType() == ltMPTOKEN)
return sle->getFieldH192(sfMPTokenIssuanceID);
if (sle->getType() == ltMPTOKEN_ISSUANCE)
return makeMptID(sle->getFieldU32(sfSequence), sle->getAccountID(sfIssuer));
return beast::zero;
};
if (before && before->getType() == ltMPTOKEN)
{
uint192 const id = getMptID(before);
changes_[id].mptAmountDelta -= before->getFieldU64(sfMPTAmount);
// Cannot delete MPToken with non-zero confidential state or non-zero public amount
if (isDelete)
{
bool const hasPublicBalance = before->getFieldU64(sfMPTAmount) > 0;
bool const hasEncryptedFields = before->isFieldPresent(sfConfidentialBalanceSpending) ||
before->isFieldPresent(sfConfidentialBalanceInbox) ||
before->isFieldPresent(sfIssuerEncryptedBalance);
if (hasPublicBalance || hasEncryptedFields)
changes_[id].deletedWithEncrypted = true;
}
}
if (after && after->getType() == ltMPTOKEN)
{
uint192 const id = getMptID(after);
changes_[id].mptAmountDelta += after->getFieldU64(sfMPTAmount);
// Encrypted field existence consistency
bool const hasIssuerBalance = after->isFieldPresent(sfIssuerEncryptedBalance);
bool const hasHolderInbox = after->isFieldPresent(sfConfidentialBalanceInbox);
bool const hasHolderSpending = after->isFieldPresent(sfConfidentialBalanceSpending);
bool const hasAnyHolder = hasHolderInbox || hasHolderSpending;
if (hasAnyHolder != hasIssuerBalance)
{
changes_[id].badConsistency = true;
}
// Privacy flag consistency
bool const hasEncrypted = hasAnyHolder || hasIssuerBalance;
if (hasEncrypted)
changes_[id].requiresPrivacyFlag = true;
}
if (before && before->getType() == ltMPTOKEN_ISSUANCE)
{
uint192 const id = getMptID(before);
if (before->isFieldPresent(sfConfidentialOutstandingAmount))
changes_[id].coaDelta -= before->getFieldU64(sfConfidentialOutstandingAmount);
changes_[id].outstandingDelta -= before->getFieldU64(sfOutstandingAmount);
}
if (after && after->getType() == ltMPTOKEN_ISSUANCE)
{
uint192 const id = getMptID(after);
auto& change = changes_[id];
bool const hasCOA = after->isFieldPresent(sfConfidentialOutstandingAmount);
std::uint64_t const coa = (*after)[~sfConfidentialOutstandingAmount].value_or(0);
std::uint64_t const oa = after->getFieldU64(sfOutstandingAmount);
if (hasCOA)
change.coaDelta += coa;
change.outstandingDelta += oa;
change.issuance = after;
// COA <= OutstandingAmount
if (coa > oa)
change.badCOA = true;
}
if (before && after && before->getType() == ltMPTOKEN && after->getType() == ltMPTOKEN)
{
uint192 const id = getMptID(after);
// sfConfidentialBalanceVersion must change when spending changes
auto const spendingBefore = (*before)[~sfConfidentialBalanceSpending];
auto const spendingAfter = (*after)[~sfConfidentialBalanceSpending];
auto const versionBefore = (*before)[~sfConfidentialBalanceVersion];
auto const versionAfter = (*after)[~sfConfidentialBalanceVersion];
if (spendingBefore.has_value() && spendingBefore != spendingAfter)
{
if (versionBefore == versionAfter)
{
changes_[id].badVersion = true;
}
}
}
}
bool
ValidConfidentialMPToken::finalize(
STTx const& tx,
TER const result,
XRPAmount const,
ReadView const& view,
beast::Journal const& j)
{
if (result != tesSUCCESS)
return true;
for (auto const& [id, checks] : changes_)
{
// Find the MPTokenIssuance
auto const issuance = [&]() -> std::shared_ptr<SLE const> {
if (checks.issuance)
return checks.issuance;
return view.read(keylet::mptIssuance(id));
}();
// Skip all invariance checks if issuance doesn't exist because that means the MPT has been
// deleted
if (!issuance)
continue;
// Cannot delete MPToken with non-zero confidential state
if (checks.deletedWithEncrypted)
{
if ((*issuance)[~sfConfidentialOutstandingAmount].value_or(0) > 0)
{
JLOG(j.fatal())
<< "Invariant failed: MPToken deleted with encrypted fields while COA > 0";
return false;
}
}
// Encrypted field existence consistency
if (checks.badConsistency)
{
JLOG(j.fatal()) << "Invariant failed: MPToken encrypted field "
"existence inconsistency";
return false;
}
// COA <= OutstandingAmount
if (checks.badCOA)
{
JLOG(j.fatal()) << "Invariant failed: Confidential outstanding amount "
"exceeds total outstanding amount";
return false;
}
// Privacy flag consistency
if (checks.requiresPrivacyFlag)
{
if (!issuance->isFlag(lsfMPTCanConfidentialAmount))
{
JLOG(j.fatal()) << "Invariant failed: MPToken has encrypted "
"fields but Issuance does not have "
"lsfMPTCanConfidentialAmount set";
return false;
}
}
// We only enforce this when Confidential Outstanding Amount changes (Convert, ConvertBack,
// ConfidentialClawback). This avoids falsely failing on Escrow or AMM operations that lock
// public tokens outside of ltMPTOKEN. Convert / ConvertBack:
// - COA and MPTAmount must have opposite deltas, which cancel each other out to zero.
// - OA remains unchanged.
// - Therefore, the net delta on both sides of the equation is zero.
//
// Clawback:
// - MPTAmount remains unchanged.
// - COA and OA must have identical deltas (mirrored on each side).
// - The equation remains balanced as both sides have equal offsets.
if (checks.coaDelta != 0)
{
if (checks.mptAmountDelta + checks.coaDelta != checks.outstandingDelta)
{
JLOG(j.fatal()) << "Invariant failed: Token conservation "
"violation for MPT "
<< to_string(id);
return false;
}
}
if (checks.badVersion)
{
JLOG(j.fatal())
<< "Invariant failed: MPToken sfConfidentialBalanceVersion not updated when "
"sfConfidentialBalanceSpending changed";
return false;
}
}
return true;
}
} // namespace xrpl

View File

@@ -2,12 +2,11 @@
//
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/nftPageMask.h>
#include <xrpl/protocol/st.h>
#include <xrpl/tx/invariants/InvariantCheckPrivilege.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {

View File

@@ -2,7 +2,6 @@
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/Book.h>
#include <xrpl/protocol/Feature.h>
@@ -14,6 +13,7 @@
#include <xrpl/tx/paths/OfferStream.h>
#include <xrpl/tx/paths/detail/FlatSets.h>
#include <xrpl/tx/paths/detail/Steps.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
#include <boost/container/flat_set.hpp>

View File

@@ -1,11 +1,11 @@
#include <xrpl/basics/Log.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/tx/paths/OfferStream.h>
#include <xrpl/tx/transactors/dex/PermissionedDEXHelpers.h>
namespace xrpl {

View File

@@ -3,7 +3,6 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -14,6 +13,7 @@
#include <xrpl/tx/transactors/account/SignerListSet.h>
#include <xrpl/tx/transactors/delegate/DelegateSet.h>
#include <xrpl/tx/transactors/did/DIDDelete.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
#include <xrpl/tx/transactors/oracle/OracleDelete.h>
#include <xrpl/tx/transactors/payment/DepositPreauth.h>
@@ -292,7 +292,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
if (!cdirFirst(ctx.view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry))
return tesSUCCESS;
std::uint32_t deletableDirEntryCount{0};
std::int32_t deletableDirEntryCount{0};
do
{
// Make sure any directory node types that we find are the kind

View File

@@ -1,6 +1,5 @@
#include <xrpl/basics/Log.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/DelegateHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -8,6 +7,7 @@
#include <xrpl/protocol/Quality.h>
#include <xrpl/protocol/st.h>
#include <xrpl/tx/transactors/account/AccountSet.h>
#include <xrpl/tx/transactors/delegate/DelegateUtils.h>
namespace xrpl {

View File

@@ -1,5 +1,5 @@
#include <xrpl/ledger/helpers/DelegateHelpers.h>
#include <xrpl/protocol/STArray.h>
#include <xrpl/tx/transactors/delegate/DelegateUtils.h>
namespace xrpl {
NotTEC

View File

@@ -1,12 +1,12 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/dex/AMMBid.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -1,12 +1,12 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/st.h>
#include <xrpl/tx/transactors/dex/AMMClawback.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
#include <xrpl/tx/transactors/dex/AMMWithdraw.h>
#include <tuple>

View File

@@ -1,14 +1,14 @@
#include <xrpl/ledger/OrderBookDB.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/STIssue.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/dex/AMMCreate.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -1,9 +1,9 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/dex/AMMDelete.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -1,12 +1,12 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/dex/AMMDeposit.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -1,4 +1,4 @@
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
namespace xrpl {

View File

@@ -1,10 +1,10 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
namespace xrpl {

View File

@@ -1,8 +1,8 @@
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
#include <xrpl/tx/transactors/dex/AMMVote.h>
namespace xrpl {

View File

@@ -1,9 +1,9 @@
#include <xrpl/basics/Number.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AMMUtils.h>
#include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
#include <xrpl/tx/transactors/dex/AMMUtils.h>
#include <xrpl/tx/transactors/dex/AMMWithdraw.h>
namespace xrpl {

View File

@@ -5,7 +5,6 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/STAmount.h>
@@ -14,6 +13,7 @@
#include <xrpl/protocol/st.h>
#include <xrpl/tx/paths/Flow.h>
#include <xrpl/tx/transactors/dex/OfferCreate.h>
#include <xrpl/tx/transactors/dex/PermissionedDEXHelpers.h>
namespace xrpl {
TxConsequences

View File

@@ -1,5 +1,5 @@
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
#include <xrpl/tx/transactors/dex/PermissionedDEXHelpers.h>
namespace xrpl {
namespace permissioned_dex {

View File

@@ -2,7 +2,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/EscrowHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -10,6 +9,8 @@
#include <xrpl/protocol/Rate.h>
#include <xrpl/tx/transactors/escrow/EscrowCancel.h>
#include <libxrpl/tx/transactors/escrow/EscrowHelpers.h>
namespace xrpl {
NotTEC

View File

@@ -6,7 +6,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/EscrowHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -16,6 +15,8 @@
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/transactors/escrow/EscrowFinish.h>
#include <libxrpl/tx/transactors/escrow/EscrowHelpers.h>
namespace xrpl {
// During an EscrowFinish, the transaction must specify both

View File

@@ -10,6 +10,7 @@
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTAmount.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/tx/transactors/token/MPTokenAuthorize.h>
namespace xrpl {
@@ -182,7 +183,8 @@ escrowUnlockApplyHelper<MPTIssue>(
return tecINSUFFICIENT_RESERVE;
}
if (auto const ter = createMPToken(view, mptID, receiver, 0); !isTesSuccess(ter))
if (auto const ter = MPTokenAuthorize::createMPToken(view, mptID, receiver, 0);
!isTesSuccess(ter))
{
return ter; // LCOV_EXCL_LINE
}

View File

@@ -386,29 +386,21 @@ LoanManage::doApply()
return tefBAD_LEDGER; // LCOV_EXCL_LINE
auto const vaultAsset = vaultSle->at(sfAsset);
auto const result = [&]() -> TER {
// Valid flag combinations are checked in preflight. No flags is valid -
// just a noop.
if (tx.isFlag(tfLoanDefault))
return defaultLoan(view, loanSle, brokerSle, vaultSle, vaultAsset, j_);
if (tx.isFlag(tfLoanImpair))
return impairLoan(view, loanSle, vaultSle, vaultAsset, j_);
if (tx.isFlag(tfLoanUnimpair))
return unimpairLoan(view, loanSle, vaultSle, vaultAsset, j_);
// Noop, as described above.
return tesSUCCESS;
}();
// Valid flag combinations are checked in preflight. No flags is valid -
// just a noop.
if (tx.isFlag(tfLoanDefault))
return defaultLoan(view, loanSle, brokerSle, vaultSle, vaultAsset, j_);
if (tx.isFlag(tfLoanImpair))
return impairLoan(view, loanSle, vaultSle, vaultAsset, j_);
if (tx.isFlag(tfLoanUnimpair))
return unimpairLoan(view, loanSle, vaultSle, vaultAsset, j_);
// Noop, as described above.
// Pre-amendment, associateAsset was only called on the noop (no flags)
// path. Post-amendment, we call associateAsset on all successful paths.
if (view.rules().enabled(fixSecurity3_1_3) && isTesSuccess(result))
{
associateAsset(*loanSle, vaultAsset);
associateAsset(*brokerSle, vaultAsset);
associateAsset(*vaultSle, vaultAsset);
}
associateAsset(*loanSle, vaultAsset);
associateAsset(*brokerSle, vaultAsset);
associateAsset(*vaultSle, vaultAsset);
return result;
return tesSUCCESS;
}
//------------------------------------------------------------------------------

View File

@@ -155,7 +155,7 @@ LoanPay::preclaim(PreclaimContext const& ctx)
if (tx.isFlag(tfLoanOverpayment) && !loanSle->isFlag(lsfLoanOverpayment))
{
JLOG(ctx.j.warn()) << "Requested overpayment on a loan that doesn't allow it";
return ctx.view.rules().enabled(fixSecurity3_1_3) ? TER{tecNO_PERMISSION} : temINVALID_FLAG;
return temINVALID_FLAG;
}
auto const principalOutstanding = loanSle->at(sfPrincipalOutstanding);

View File

@@ -28,7 +28,7 @@ LoanSet::preflight(PreflightContext const& ctx)
auto const& tx = ctx.tx;
// Special case for Batch inner transactions
if (tx.isFlag(tfInnerBatchTxn) && ctx.rules.enabled(featureBatchV1_1) &&
if (tx.isFlag(tfInnerBatchTxn) && ctx.rules.enabled(featureBatch) &&
!tx.isFieldPresent(sfCounterparty))
{
auto const parentBatchId = ctx.parentBatchId.value_or(uint256{0});

View File

@@ -1,10 +1,10 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/nft/NFTokenAcceptOffer.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {

View File

@@ -1,8 +1,8 @@
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/nft/NFTokenBurn.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {

View File

@@ -1,8 +1,8 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/nft/NFTokenCancelOffer.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
#include <boost/endian/conversion.hpp>

View File

@@ -1,8 +1,8 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/nft/NFTokenCreateOffer.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {

View File

@@ -1,7 +1,7 @@
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/nft/NFTokenModify.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
namespace xrpl {

View File

@@ -1,16 +1,15 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/algorithm.h>
#include <xrpl/ledger/Dir.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/STArray.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/nftPageMask.h>
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
#include <functional>
#include <memory>

View File

@@ -1,9 +1,7 @@
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DelegateHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Quality.h>
@@ -11,6 +9,8 @@
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/tx/paths/RippleCalc.h>
#include <xrpl/tx/transactors/delegate/DelegateUtils.h>
#include <xrpl/tx/transactors/dex/PermissionedDEXHelpers.h>
#include <xrpl/tx/transactors/payment/Payment.h>
namespace xrpl {
@@ -289,7 +289,7 @@ Payment::preclaim(PreclaimContext const& ctx)
// transaction would succeed.
return tecNO_DST;
}
if (partialPaymentAllowed)
if (ctx.view.open() && partialPaymentAllowed)
{
// You cannot fund an account with a partial payment.
// Make retry work smaller, by rejecting this.
@@ -328,7 +328,7 @@ Payment::preclaim(PreclaimContext const& ctx)
}
// Payment with at least one intermediate step and uses transitive balances.
if (hasPaths || sendMax || !dstAmount.native())
if ((hasPaths || sendMax || !dstAmount.native()) && ctx.view.open())
{
STPathSet const& paths = ctx.tx.getFieldPathSet(sfPaths);
@@ -559,23 +559,18 @@ Payment::doApply()
// This is the total reserve in drops.
auto const reserve = view().fees().accountReserve(ownerCount);
// In a delegated payment, the fee payer is the delegated account,
// not the source account (account_).
bool const accountIsPayer = (ctx_.tx.getFeePayer() == account_);
// preFeeBalance_ is the balance on the sending account BEFORE the
// fees were charged. We want to make sure we have enough reserve
// to send. Allow final spend to use reserve for fee.
auto const mmm = std::max(reserve, ctx_.tx.getFieldAmount(sfFee).xrp());
// preFeeBalance_ is the balance on the source account (account_) BEFORE the fees
// were charged. If source account is the fee payer, it must also cover the fee.
// The final spend may use the reserve to cover fees.
auto const minRequiredFunds =
accountIsPayer ? std::max(reserve, ctx_.tx.getFieldAmount(sfFee).xrp()) : reserve;
if (preFeeBalance_ < dstAmount.xrp() + minRequiredFunds)
if (preFeeBalance_ < dstAmount.xrp() + mmm)
{
// Vote no. However the transaction might succeed, if applied in
// a different order.
JLOG(j_.trace()) << "Delay transaction: Insufficient funds: " << to_string(preFeeBalance_)
<< " / " << to_string(dstAmount.xrp() + minRequiredFunds) << " ("
<< to_string(reserve) << ")";
<< " / " << to_string(dstAmount.xrp() + mmm) << " (" << to_string(reserve)
<< ")";
return tecUNFUNDED_PAYMENT;
}

View File

@@ -1,7 +1,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/PaymentChannelHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/PayChan.h>
@@ -9,6 +8,8 @@
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/tx/transactors/payment_channel/PaymentChannelClaim.h>
#include <libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.h>
namespace xrpl {
bool

View File

@@ -1,9 +1,10 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/PaymentChannelHelpers.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/tx/transactors/payment_channel/PaymentChannelFund.h>
#include <libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.h>
namespace xrpl {
TxConsequences

Some files were not shown because too many files have changed in this diff Show More