Move the ValidPseudoAccounts class back to its original location

- The class didn't actually change much, if at all, but somehow got
  relocated.
- This should make the review easier, and reduce the footprint of the
  PR.
This commit is contained in:
Ed Hennis
2025-11-25 13:25:48 -05:00
parent 49ee70ea28
commit 77e3bbdc89
2 changed files with 124 additions and 122 deletions

View File

@@ -1731,6 +1731,102 @@ ValidPermissionedDomain::finalize(
(sleStatus_[1] ? check(*sleStatus_[1], j) : true);
}
//------------------------------------------------------------------------------
void
ValidPseudoAccounts::visitEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)
{
if (isDelete)
// Deletion is ignored
return;
if (after && after->getType() == ltACCOUNT_ROOT)
{
bool const isPseudo = [&]() {
// isPseudoAccount checks that any of the pseudo-account fields are
// set.
if (isPseudoAccount(after))
return true;
// Not all pseudo-accounts have a zero sequence, but all accounts
// with a zero sequence had better be pseudo-accounts.
if (after->at(sfSequence) == 0)
return true;
return false;
}();
if (isPseudo)
{
// Pseudo accounts must have the following properties:
// 1. Exactly one of the pseudo-account fields is set.
// 2. The sequence number is not changed.
// 3. The lsfDisableMaster, lsfDefaultRipple, and lsfDepositAuth
// flags are set.
// 4. The RegularKey is not set.
{
std::vector<SField const*> const& fields =
getPseudoAccountFields();
auto const numFields = std::count_if(
fields.begin(),
fields.end(),
[&after](SField const* sf) -> bool {
return after->isFieldPresent(*sf);
});
if (numFields != 1)
{
std::stringstream error;
error << "pseudo-account has " << numFields
<< " pseudo-account fields set";
errors_.emplace_back(error.str());
}
}
if (before && before->at(sfSequence) != after->at(sfSequence))
{
errors_.emplace_back("pseudo-account sequence changed");
}
if (!after->isFlag(
lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth))
{
errors_.emplace_back("pseudo-account flags are not set");
}
if (after->isFieldPresent(sfRegularKey))
{
errors_.emplace_back("pseudo-account has a regular key");
}
}
}
}
bool
ValidPseudoAccounts::finalize(
STTx const& tx,
TER const,
XRPAmount const,
ReadView const& view,
beast::Journal const& j)
{
bool const enforce = view.rules().enabled(featureSingleAssetVault);
XRPL_ASSERT(
errors_.empty() || enforce,
"ripple::ValidPseudoAccounts::finalize : no bad "
"changes or enforce invariant");
if (!errors_.empty())
{
for (auto const& error : errors_)
{
JLOG(j.fatal()) << "Invariant failed: " << error;
}
if (enforce)
return false;
}
return true;
}
//------------------------------------------------------------------------------
void
ValidPermissionedDEX::visitEntry(
bool,
@@ -2237,100 +2333,6 @@ NoModifiedUnmodifiableFields::finalize(
//------------------------------------------------------------------------------
void
ValidPseudoAccounts::visitEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)
{
if (isDelete)
// Deletion is ignored
return;
if (after && after->getType() == ltACCOUNT_ROOT)
{
bool const isPseudo = [&]() {
// isPseudoAccount checks that any of the pseudo-account fields are
// set.
if (isPseudoAccount(after))
return true;
// Not all pseudo-accounts have a zero sequence, but all accounts
// with a zero sequence had better be pseudo-accounts.
if (after->at(sfSequence) == 0)
return true;
return false;
}();
if (isPseudo)
{
// Pseudo accounts must have the following properties:
// 1. Exactly one of the pseudo-account fields is set.
// 2. The sequence number is not changed.
// 3. The lsfDisableMaster, lsfDefaultRipple, and lsfDepositAuth
// flags are set.
// 4. The RegularKey is not set.
{
std::vector<SField const*> const& fields =
getPseudoAccountFields();
auto const numFields = std::count_if(
fields.begin(),
fields.end(),
[&after](SField const* sf) -> bool {
return after->isFieldPresent(*sf);
});
if (numFields != 1)
{
std::stringstream error;
error << "pseudo-account has " << numFields
<< " pseudo-account fields set";
errors_.emplace_back(error.str());
}
}
if (before && before->at(sfSequence) != after->at(sfSequence))
{
errors_.emplace_back("pseudo-account sequence changed");
}
if (!after->isFlag(
lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth))
{
errors_.emplace_back("pseudo-account flags are not set");
}
if (after->isFieldPresent(sfRegularKey))
{
errors_.emplace_back("pseudo-account has a regular key");
}
}
}
}
bool
ValidPseudoAccounts::finalize(
STTx const& tx,
TER const,
XRPAmount const,
ReadView const& view,
beast::Journal const& j)
{
bool const enforce = view.rules().enabled(featureSingleAssetVault);
XRPL_ASSERT(
errors_.empty() || enforce,
"ripple::ValidPseudoAccounts::finalize : no bad "
"changes or enforce invariant");
if (!errors_.empty())
{
for (auto const& error : errors_)
{
JLOG(j.fatal()) << "Invariant failed: " << error;
}
if (enforce)
return false;
}
return true;
}
//------------------------------------------------------------------------------
void
ValidLoanBroker::visitEntry(
bool isDelete,

View File

@@ -612,6 +612,34 @@ public:
beast::Journal const&);
};
/**
* @brief Invariants: Pseudo-accounts have valid and consisent properties
*
* Pseudo-accounts have certain properties, and some of those properties are
* unique to pseudo-accounts. Check that all pseudo-accounts are following the
* rules, and that only pseudo-accounts look like pseudo-accounts.
*
*/
class ValidPseudoAccounts
{
std::vector<std::string> errors_;
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&);
};
class ValidPermissionedDEX
{
bool regularOffers_ = false;
@@ -725,34 +753,6 @@ public:
beast::Journal const&);
};
/**
* @brief Invariants: Pseudo-accounts have valid and consisent properties
*
* Pseudo-accounts have certain properties, and some of those properties are
* unique to pseudo-accounts. Check that all pseudo-accounts are following the
* rules, and that only pseudo-accounts look like pseudo-accounts.
*
*/
class ValidPseudoAccounts
{
std::vector<std::string> errors_;
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&);
};
/**
* @brief Invariants: Loan brokers are internally consistent
*