mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
Code cleanup
This commit is contained in:
@@ -124,7 +124,7 @@ std::uint8_t constexpr vaultStrategyFirstComeFirstServe = 1;
|
||||
|
||||
/** Maximum recursion depth for vault shares being put as an asset inside
|
||||
* another vault; counted from 0 */
|
||||
std::uint8_t constexpr maxFreezeCheckDepth = 5;
|
||||
std::uint8_t constexpr maxAssetCheckDepth = 5;
|
||||
|
||||
/** A ledger index. */
|
||||
using LedgerIndex = std::uint32_t;
|
||||
|
||||
@@ -93,7 +93,9 @@ struct JsonOptions
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
requires requires(T const& t) { t.getJson(JsonOptions::none); }
|
||||
requires requires(T const& t) {
|
||||
{ t.getJson(JsonOptions::none) } -> std::convertible_to<Json::Value>;
|
||||
}
|
||||
Json::Value
|
||||
to_json(T const& t)
|
||||
{
|
||||
|
||||
@@ -61,8 +61,7 @@ using NodeID = base_uint<160, detail::NodeIDTag>;
|
||||
/** MPTID is a 192-bit value representing MPT Issuance ID,
|
||||
* which is a concatenation of a 32-bit sequence (big endian)
|
||||
* and a 160-bit account */
|
||||
// TODO - edhennis - Add a tag
|
||||
using MPTID = uint192;
|
||||
using MPTID = base_uint<192>;
|
||||
|
||||
/** XRP currency. */
|
||||
Currency const&
|
||||
|
||||
@@ -197,9 +197,9 @@ TYPED_SFIELD(sfVaultID, UINT256, 35)
|
||||
|
||||
// number (common)
|
||||
TYPED_SFIELD(sfNumber, NUMBER, 1)
|
||||
TYPED_SFIELD(sfAssetsAvailable, NUMBER, 2)
|
||||
TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3)
|
||||
TYPED_SFIELD(sfAssetsTotal, NUMBER, 4)
|
||||
TYPED_SFIELD(sfAssetsAvailable, NUMBER, 2)
|
||||
TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3)
|
||||
TYPED_SFIELD(sfAssetsTotal, NUMBER, 4)
|
||||
TYPED_SFIELD(sfLossUnrealized, NUMBER, 5)
|
||||
|
||||
// currency amount (common)
|
||||
|
||||
@@ -89,7 +89,6 @@ JSS(SettleDelay); // in: TransactionSign
|
||||
JSS(SendMax); // in: TransactionSign
|
||||
JSS(Sequence); // in/out: TransactionSign; field.
|
||||
JSS(SetFlag); // field.
|
||||
JSS(SharesTotal); // out: Vault
|
||||
JSS(Signer); // field.
|
||||
JSS(Signers); // field.
|
||||
JSS(SigningPubKey); // field.
|
||||
@@ -101,7 +100,6 @@ JSS(TransactionType); // in: TransactionSign.
|
||||
JSS(TransferRate); // in: TransferRate.
|
||||
JSS(TxnSignature); // field.
|
||||
JSS(URI); // field.
|
||||
JSS(VaultID); // field.
|
||||
JSS(VoteSlots); // out: AMM Vote
|
||||
JSS(aborted); // out: InboundLedger
|
||||
JSS(accepted); // out: LedgerToJson, OwnerInfo, SubmitTransaction
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STBase.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STNumber.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
@@ -50,7 +50,7 @@ Vault::set(SetArgs const& args)
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::VaultSet;
|
||||
jv[jss::Account] = args.owner.human();
|
||||
jv[jss::VaultID] = to_string(args.id);
|
||||
jv[sfVaultID] = to_string(args.id);
|
||||
return jv;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ Vault::del(DeleteArgs const& args)
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::VaultDelete;
|
||||
jv[jss::Account] = args.owner.human();
|
||||
jv[jss::VaultID] = to_string(args.id);
|
||||
jv[sfVaultID] = to_string(args.id);
|
||||
return jv;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ Vault::deposit(DepositArgs const& args)
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::VaultDeposit;
|
||||
jv[jss::Account] = args.depositor.human();
|
||||
jv[jss::VaultID] = to_string(args.id);
|
||||
jv[sfVaultID] = to_string(args.id);
|
||||
jv[jss::Amount] = to_json(args.amount);
|
||||
return jv;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ Vault::withdraw(WithdrawArgs const& args)
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::VaultWithdraw;
|
||||
jv[jss::Account] = args.depositor.human();
|
||||
jv[jss::VaultID] = to_string(args.id);
|
||||
jv[sfVaultID] = to_string(args.id);
|
||||
jv[jss::Amount] = to_json(args.amount);
|
||||
return jv;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ Vault::clawback(ClawbackArgs const& args)
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::VaultClawback;
|
||||
jv[jss::Account] = args.issuer.human();
|
||||
jv[jss::VaultID] = to_string(args.id);
|
||||
jv[sfVaultID] = to_string(args.id);
|
||||
jv[jss::Holder] = args.holder.human();
|
||||
if (args.amount)
|
||||
jv[jss::Amount] = to_json(*args.amount);
|
||||
|
||||
@@ -227,8 +227,7 @@ applyCreate(
|
||||
auto const ammKeylet = keylet::amm(amount.issue(), amount2.issue());
|
||||
|
||||
// Mitigate same account exists possibility
|
||||
auto const maybeAccount =
|
||||
createPseudoAccount(sb, ammKeylet.key, PseudoAccountOwnerType::AMM);
|
||||
auto const maybeAccount = createPseudoAccount(sb, ammKeylet.key, sfAMMID);
|
||||
// AMM account already exists (should not happen)
|
||||
if (!maybeAccount)
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx)
|
||||
return tecWRONG_ASSET;
|
||||
|
||||
std::uint32_t const issueFlags = mptIssue->getFieldU32(sfFlags);
|
||||
if (!(issueFlags & lsfMPTCanClawback) || !(issueFlags & lsfMPTCanLock))
|
||||
if (!(issueFlags & lsfMPTCanClawback))
|
||||
return tecNO_PERMISSION;
|
||||
}
|
||||
else if (asset.holds<Issue>())
|
||||
|
||||
@@ -56,10 +56,10 @@ VaultCreate::preflight(PreflightContext const& ctx)
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
if (auto const data = ctx.tx[~sfWithdrawalPolicy])
|
||||
if (auto const withdrawalPolicy = ctx.tx[~sfWithdrawalPolicy])
|
||||
{
|
||||
// Enforce valid withdrawal policy
|
||||
if (*data != vaultStrategyFirstComeFirstServe)
|
||||
if (*withdrawalPolicy != vaultStrategyFirstComeFirstServe)
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
@@ -151,22 +151,21 @@ VaultCreate::doApply()
|
||||
// we can consider downgrading them to `tef` or `tem`.
|
||||
|
||||
auto const& tx = ctx_.tx;
|
||||
auto const& ownerId = account_;
|
||||
auto sequence = tx.getSeqValue();
|
||||
auto owner = view().peek(keylet::account(account_));
|
||||
if (owner == nullptr)
|
||||
return tefINTERNAL;
|
||||
|
||||
auto owner = view().peek(keylet::account(ownerId));
|
||||
auto vault = std::make_shared<SLE>(keylet::vault(ownerId, sequence));
|
||||
auto vault = std::make_shared<SLE>(keylet::vault(account_, sequence));
|
||||
|
||||
if (auto ter = dirLink(view(), ownerId, vault))
|
||||
if (auto ter = dirLink(view(), account_, vault))
|
||||
return ter;
|
||||
// Should the next 3 lines be folded into `dirLink`?
|
||||
adjustOwnerCount(view(), owner, 1, j_);
|
||||
auto ownerCount = owner->at(sfOwnerCount);
|
||||
if (mPriorBalance < view().fees().accountReserve(ownerCount))
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
|
||||
auto maybePseudo = createPseudoAccount(
|
||||
view(), vault->key(), PseudoAccountOwnerType::Vault);
|
||||
auto maybePseudo = createPseudoAccount(view(), vault->key(), sfVaultID);
|
||||
if (!maybePseudo)
|
||||
return maybePseudo.error();
|
||||
auto& pseudo = *maybePseudo;
|
||||
@@ -206,7 +205,7 @@ VaultCreate::doApply()
|
||||
|
||||
vault->at(sfFlags) = txFlags & tfVaultPrivate;
|
||||
vault->at(sfSequence) = sequence;
|
||||
vault->at(sfOwner) = ownerId;
|
||||
vault->at(sfOwner) = account_;
|
||||
vault->at(sfAccount) = pseudoId;
|
||||
vault->at(sfAsset) = asset;
|
||||
vault->at(sfAssetsTotal) = Number(0);
|
||||
|
||||
@@ -83,7 +83,7 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
|
||||
if (isFrozen(ctx.view, account, share))
|
||||
return tecLOCKED;
|
||||
|
||||
if ((vault->getFlags() & tfVaultPrivate) && account != vault->at(sfOwner))
|
||||
if (vault->isFlag(tfVaultPrivate) && account != vault->at(sfOwner))
|
||||
{
|
||||
auto const maybeDomainID = sleIssuance->at(~sfDomainID);
|
||||
// Since this is a private vault and the account is not its owner, we
|
||||
@@ -176,7 +176,7 @@ VaultDeposit::doApply()
|
||||
}
|
||||
|
||||
// If the vault is private, set the authorized flag for the vault owner
|
||||
if (vault->getFlags() & tfVaultPrivate)
|
||||
if (vault->isFlag(tfVaultPrivate))
|
||||
{
|
||||
if (auto const err = MPTokenAuthorize::authorize(
|
||||
view(),
|
||||
|
||||
@@ -155,6 +155,12 @@ isFrozen(
|
||||
MPTIssue const& mptIssue,
|
||||
int depth = 0);
|
||||
|
||||
/**
|
||||
* isFrozen check is recursive for MPT shares in a vault, descending to assets
|
||||
* in the vault. These assets could be themselves MPT shares in another vault.
|
||||
* For this reason we limit depth of check, up to maxAssetCheckDepth. If this
|
||||
* depth is exceeded, we return true (i.e. the asset is considered frozen).
|
||||
*/
|
||||
[[nodiscard]] inline bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
@@ -502,14 +508,19 @@ dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object);
|
||||
AccountID
|
||||
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
||||
|
||||
// Which of the owner-object fields should we set: sfAMMID, sfVaultID
|
||||
enum class PseudoAccountOwnerType : int { AMM, Vault };
|
||||
|
||||
/**
|
||||
*
|
||||
* Create pseudo-account, storing pseudoOwnerKey into ownerField.
|
||||
*
|
||||
* The list of valid ownerField is maintained in View.cpp and the caller to
|
||||
* this function must perform necessary amendment check(s) before using a
|
||||
* field. The amendment check is **not** performed in createPseudoAccount.
|
||||
*/
|
||||
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
|
||||
createPseudoAccount(
|
||||
ApplyView& view,
|
||||
uint256 const& pseudoOwnerKey,
|
||||
PseudoAccountOwnerType type);
|
||||
SField const& ownerField);
|
||||
|
||||
// Returns true iff sleAcct is a pseudo-account.
|
||||
//
|
||||
@@ -691,12 +702,6 @@ transferXRP(
|
||||
STAmount const& amount,
|
||||
beast::Journal j);
|
||||
|
||||
struct TokenDescriptor
|
||||
{
|
||||
std::shared_ptr<SLE const> token;
|
||||
std::shared_ptr<SLE const> issuance;
|
||||
};
|
||||
|
||||
/** Check if the account lacks required authorization.
|
||||
*
|
||||
* Return tecNO_AUTH or tecNO_LINE if it does
|
||||
@@ -711,6 +716,13 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account);
|
||||
* from preclaim, the user should convert result tecEXPIRED to tesSUCCESS and
|
||||
* proceed to also check permissions with enforceMPTokenAuthorization inside
|
||||
* doApply. This will ensure that any expired credentials are deleted.
|
||||
*
|
||||
* requireAuth check is recursive for MPT shares in a vault, descending to
|
||||
* assets in the vault. These assets could be themselves MPT shares in another
|
||||
* vault. For this reason we limit depth of check, up to maxAssetCheckDepth.
|
||||
* This function will return tecKILLED if maximum depth is exceeded.
|
||||
* Transaction VaultCreate checks for tecKILLED to prevent such vaults being
|
||||
* created.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
requireAuth(
|
||||
@@ -728,7 +740,7 @@ requireAuth(
|
||||
* in order for the transactor to proceed to doApply.
|
||||
*
|
||||
* This function will create MPToken (if needed) on the basis of any
|
||||
* non-expired credentals and will delete any expired credentials, indirectly
|
||||
* non-expired credentials and will delete any expired credentials, indirectly
|
||||
* via verifyValidDomain, as per DomainID (if set in MPTokenIssuance).
|
||||
*
|
||||
* The caller does NOT need to ensure that DomainID is actually set - this
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpld/ledger/ReadView.h>
|
||||
// TODO: Move the helper out of the `app` module.
|
||||
#include <xrpld/app/misc/CredentialHelpers.h>
|
||||
#include <xrpld/app/tx/detail/MPTokenAuthorize.h>
|
||||
#include <xrpld/ledger/ReadView.h>
|
||||
#include <xrpld/ledger/View.h>
|
||||
|
||||
#include <xrpl/basics/Expected.h>
|
||||
@@ -328,8 +327,8 @@ isVaultPseudoAccountFrozen(
|
||||
if (!mptIssuer->isFieldPresent(sfVaultID))
|
||||
return false; // not a Vault pseudo-account, common case
|
||||
|
||||
if (depth >= maxFreezeCheckDepth)
|
||||
return true; // fail at maximum 2^maxFreezeCheckDepth checks
|
||||
if (depth >= maxAssetCheckDepth)
|
||||
return true; // fail at maximum 2^maxAssetCheckDepth checks
|
||||
|
||||
auto const vault =
|
||||
view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID)));
|
||||
@@ -1063,12 +1062,31 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
|
||||
return beast::zero;
|
||||
}
|
||||
|
||||
// Note, the list of the pseudo-account designator fields below MUST be
|
||||
// maintained but it does NOT need to be amendment-gated, since a
|
||||
// non-active amendment will not set any field, by definition. Specific
|
||||
// properties of a pseudo-account are NOT checked here, that's what
|
||||
// InvariantCheck is for.
|
||||
static std::array<SField const*, 2> const pseudoAccountOwnerFields = {
|
||||
&sfAMMID, //
|
||||
&sfVaultID, //
|
||||
};
|
||||
|
||||
Expected<std::shared_ptr<SLE>, TER>
|
||||
createPseudoAccount(
|
||||
ApplyView& view,
|
||||
uint256 const& pseudoOwnerKey,
|
||||
PseudoAccountOwnerType type)
|
||||
SField const& ownerField)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
std::count_if(
|
||||
pseudoAccountOwnerFields.begin(),
|
||||
pseudoAccountOwnerFields.end(),
|
||||
[&ownerField](SField const* sf) -> bool {
|
||||
return *sf == ownerField;
|
||||
}) == 1,
|
||||
"ripple::createPseudoAccount : valid owner field");
|
||||
|
||||
auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey);
|
||||
if (accountId == beast::zero)
|
||||
return Unexpected(tecDUPLICATE);
|
||||
@@ -1081,12 +1099,10 @@ createPseudoAccount(
|
||||
// Pseudo-accounts can't submit transactions, so set the sequence number
|
||||
// to 0 to make them easier to spot and verify, and add an extra level
|
||||
// of protection.
|
||||
std::uint32_t const seqno = //
|
||||
view.rules().enabled(featureSingleAssetVault) //
|
||||
? 0 //
|
||||
: view.rules().enabled(featureDeletableAccounts) //
|
||||
? view.seq() //
|
||||
: 1;
|
||||
std::uint32_t const seqno = //
|
||||
view.rules().enabled(featureSingleAssetVault) //
|
||||
? 0 //
|
||||
: view.seq();
|
||||
account->setFieldU32(sfSequence, seqno);
|
||||
// Ignore reserves requirement, disable the master key, allow default
|
||||
// rippling, and enable deposit authorization to prevent payments into
|
||||
@@ -1094,19 +1110,7 @@ createPseudoAccount(
|
||||
account->setFieldU32(
|
||||
sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
|
||||
// Link the pseudo-account with its owner object.
|
||||
switch (type)
|
||||
{
|
||||
case PseudoAccountOwnerType::AMM:
|
||||
account->setFieldH256(sfAMMID, pseudoOwnerKey);
|
||||
break;
|
||||
case PseudoAccountOwnerType::Vault:
|
||||
account->setFieldH256(sfVaultID, pseudoOwnerKey);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE( // LCOV_EXCL_LINE
|
||||
"ripple::createPseudoAccount : unknown owner key type"); // LCOV_EXCL_LINE
|
||||
return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE
|
||||
}
|
||||
account->setFieldH256(ownerField, pseudoOwnerKey);
|
||||
|
||||
view.insert(account);
|
||||
|
||||
@@ -1116,21 +1120,13 @@ createPseudoAccount(
|
||||
[[nodiscard]] bool
|
||||
isPseudoAccount(std::shared_ptr<SLE const> sleAcct)
|
||||
{
|
||||
// Note, the list of the pseudo-account designator fields below MUST be
|
||||
// maintained but it does NOT need to be amendment-gated, since a non-active
|
||||
// amendment will not set any field, by definition. Specific properties of a
|
||||
// pseudo-account are NOT checked here, that's what InvariantCheck is for.
|
||||
static std::array<SField const*, 2> const fields = //
|
||||
{
|
||||
&sfAMMID, //
|
||||
&sfVaultID, //
|
||||
};
|
||||
|
||||
// Intentionally use defensive coding here because it's cheap and makes the
|
||||
// semantics of true return value clean.
|
||||
return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT &&
|
||||
std::count_if(
|
||||
fields.begin(), fields.end(), [&sleAcct](SField const* sf) -> bool {
|
||||
pseudoAccountOwnerFields.begin(),
|
||||
pseudoAccountOwnerFields.end(),
|
||||
[&sleAcct](SField const* sf) -> bool {
|
||||
return sleAcct->isFieldPresent(*sf);
|
||||
}) > 0;
|
||||
}
|
||||
@@ -2301,7 +2297,7 @@ requireAuth(
|
||||
if (!sleVault)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
if (depth >= maxFreezeCheckDepth)
|
||||
if (depth >= maxAssetCheckDepth)
|
||||
return tecKILLED; // VaultCreate looks for this error code
|
||||
|
||||
auto const asset = sleVault->at(sfAsset);
|
||||
@@ -2342,8 +2338,8 @@ requireAuth(
|
||||
return tecNO_AUTH;
|
||||
|
||||
// mptoken must be authorized if issuance enabled requireAuth
|
||||
if (sleIssuance->getFieldU32(sfFlags) & lsfMPTRequireAuth &&
|
||||
!(sleToken->getFlags() & lsfMPTAuthorized))
|
||||
if (sleIssuance->isFlag(lsfMPTRequireAuth) &&
|
||||
!(sleToken->isFlag(lsfMPTAuthorized)))
|
||||
return tecNO_AUTH;
|
||||
|
||||
// We are authorized by permissioned domain.
|
||||
@@ -2364,7 +2360,7 @@ enforceMPTokenAuthorization(
|
||||
return tefINTERNAL;
|
||||
|
||||
XRPL_ASSERT(
|
||||
sleIssuance->getFlags() & lsfMPTRequireAuth,
|
||||
sleIssuance->isFlag(lsfMPTRequireAuth),
|
||||
"ripple::enforceMPTokenAuthorization : authorization required");
|
||||
|
||||
if (account == sleIssuance->at(sfIssuer))
|
||||
@@ -2401,7 +2397,7 @@ enforceMPTokenAuthorization(
|
||||
XRPL_ASSERT(
|
||||
sleToken != nullptr && !maybeDomainID.has_value(),
|
||||
"ripple::enforceMPTokenAuthorization : found MPToken");
|
||||
if (sleToken->getFlags() & lsfMPTAuthorized)
|
||||
if (sleToken->isFlag(lsfMPTAuthorized))
|
||||
return tesSUCCESS;
|
||||
|
||||
return tecNO_AUTH;
|
||||
|
||||
Reference in New Issue
Block a user