From c3fdbc04306a0b0fd7738faf07a05697da19c7ef Mon Sep 17 00:00:00 2001 From: Shawn Xie <35279399+shawnxie999@users.noreply.github.com> Date: Wed, 1 Oct 2025 13:02:11 -0400 Subject: [PATCH] SFields and formats (#5795) --- include/xrpl/protocol/LedgerFormats.h | 1 + include/xrpl/protocol/Protocol.h | 5 +++++ include/xrpl/protocol/TxFlags.h | 3 ++- include/xrpl/protocol/detail/features.macro | 1 + include/xrpl/protocol/detail/ledger_entries.macro | 7 +++++++ include/xrpl/protocol/detail/sfields.macro | 10 ++++++++++ include/xrpl/protocol/detail/transactions.macro | 13 +++++++++++++ src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp | 4 ++++ 8 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/xrpl/protocol/LedgerFormats.h b/include/xrpl/protocol/LedgerFormats.h index e3efe8fec2..f4eae88f3c 100644 --- a/include/xrpl/protocol/LedgerFormats.h +++ b/include/xrpl/protocol/LedgerFormats.h @@ -187,6 +187,7 @@ enum LedgerSpecificFlags { lsfMPTCanTrade = 0x00000010, lsfMPTCanTransfer = 0x00000020, lsfMPTCanClawback = 0x00000040, + lsfMPTNoConfidentialTransfer = 0x00000080, // ltMPTOKEN lsfMPTAuthorized = 0x00000002, diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index a0fcfee34c..ae3d3563a6 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -179,6 +179,11 @@ std::size_t constexpr permissionMaxSize = 10; /** The maximum number of transactions that can be in a batch. */ std::size_t constexpr maxBatchTxCount = 8; +/** EC ElGamal ciphertext length 33-byte */ +std::size_t constexpr ecGamalEncryptedLength = 33; + +/** EC ElGamal ciphertext length: two 33-byte components concatenated */ +std::size_t constexpr ecGamalEncryptedTotalLength = 66; } // namespace ripple #endif diff --git a/include/xrpl/protocol/TxFlags.h b/include/xrpl/protocol/TxFlags.h index a37474b780..38c6eb27b9 100644 --- a/include/xrpl/protocol/TxFlags.h +++ b/include/xrpl/protocol/TxFlags.h @@ -148,8 +148,9 @@ constexpr std::uint32_t const tfMPTCanEscrow = lsfMPTCanEscrow; constexpr std::uint32_t const tfMPTCanTrade = lsfMPTCanTrade; constexpr std::uint32_t const tfMPTCanTransfer = lsfMPTCanTransfer; constexpr std::uint32_t const tfMPTCanClawback = lsfMPTCanClawback; +constexpr std::uint32_t const tfMPTNoConfidentialTransfer = lsfMPTNoConfidentialTransfer; constexpr std::uint32_t const tfMPTokenIssuanceCreateMask = - ~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback); + ~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback | tfMPTNoConfidentialTransfer); // MPTokenAuthorize flags: constexpr std::uint32_t const tfMPTUnauthorize = 0x00000001; diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 9aacbbe3d9..ed25da8c39 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -32,6 +32,7 @@ // If you add an amendment here, then do not forget to increment `numFeatures` // in include/xrpl/protocol/Feature.h. +XRPL_FEATURE(ConfidentialTransfer, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (PriceOracleOrder, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo) diff --git a/include/xrpl/protocol/detail/ledger_entries.macro b/include/xrpl/protocol/detail/ledger_entries.macro index ac9ebc6069..868bc6a88a 100644 --- a/include/xrpl/protocol/detail/ledger_entries.macro +++ b/include/xrpl/protocol/detail/ledger_entries.macro @@ -412,6 +412,8 @@ LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({ {sfPreviousTxnID, soeREQUIRED}, {sfPreviousTxnLgrSeq, soeREQUIRED}, {sfDomainID, soeOPTIONAL}, + {sfIssuerElGamalPublicKey, soeOPTIONAL}, + {sfConfidentialOutstandingAmount, soeOPTIONAL}, })) /** A ledger object which tracks MPToken @@ -425,6 +427,11 @@ LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({ {sfOwnerNode, soeREQUIRED}, {sfPreviousTxnID, soeREQUIRED}, {sfPreviousTxnLgrSeq, soeREQUIRED}, + {sfConfidentialBalanceInbox, soeOPTIONAL}, + {sfConfidentialBalanceSpending, soeOPTIONAL}, + {sfConfidentialBalanceVersion, soeOPTIONAL}, + {sfIssuerEncryptedBalance, soeOPTIONAL}, + {sfHolderElGamalPublicKey, soeOPTIONAL}, })) /** A ledger object which tracks Oracle diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index 537fcae479..40c8bd7ddb 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -114,6 +114,7 @@ TYPED_SFIELD(sfVoteWeight, UINT32, 48) TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50) TYPED_SFIELD(sfOracleDocumentID, UINT32, 51) TYPED_SFIELD(sfPermissionValue, UINT32, 52) +TYPED_SFIELD(sfConfidentialBalanceVersion, UINT32, 53) // 64-bit integers (common) TYPED_SFIELD(sfIndexNext, UINT64, 1) @@ -145,6 +146,7 @@ TYPED_SFIELD(sfMPTAmount, UINT64, 26, SField::sMD_BaseTen|SFie TYPED_SFIELD(sfIssuerNode, UINT64, 27) TYPED_SFIELD(sfSubjectNode, UINT64, 28) TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::sMD_BaseTen|SField::sMD_Default) +TYPED_SFIELD(sfConfidentialOutstandingAmount, UINT64, 30, SField::sMD_BaseTen|SField::sMD_Default) // 128-bit TYPED_SFIELD(sfEmailHash, UINT128, 1) @@ -275,6 +277,14 @@ 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(sfIssuerElGamalPublicKey, VL, 35) +TYPED_SFIELD(sfHolderElGamalPublicKey, VL, 36) +TYPED_SFIELD(sfZKProof, VL, 37) +TYPED_SFIELD(sfHolderEncryptedAmount, VL, 38) +TYPED_SFIELD(sfIssuerEncryptedAmount, VL, 39) // account (common) TYPED_SFIELD(sfAccount, ACCOUNT, 1) diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index bfbc18aa1b..63b340bcc8 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -715,6 +715,19 @@ TRANSACTION(ttBATCH, 71, Batch, {sfBatchSigners, soeOPTIONAL}, })) +// /** This transaction type converts into confidential MPT balance. */ +// TRANSACTION(ttCONFIDENTIAL_CONVERT, 72, ConfidentialConvert, +// Delegation::delegatable, +// featureConfidentialTransfer, +// ({ +// {sfMPTokenIssuanceID, soeREQUIRED}, +// {sfMPTAmount, soeREQUIRED}, +// {sfHolderElGamalPublicKey, soeOPTIONAL}, +// {sfHolderEncryptedAmount, soeREQUIRED}, +// {sfIssuerEncryptedAmount, 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 diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp b/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp index da3b57c8fe..556fe1d978 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp @@ -36,6 +36,10 @@ MPTokenIssuanceCreate::preflight(PreflightContext const& ctx) ctx.rules.enabled(featureSingleAssetVault))) return temDISABLED; + if (ctx.tx.getFlags() & tfMPTNoConfidentialTransfer && + !ctx.rules.enabled(featureConfidentialTransfer)) + return temDISABLED; + if (auto const ret = preflight1(ctx); !isTesSuccess(ret)) return ret;