feat: Add support for deep freeze (#1875)

fixes #1826
This commit is contained in:
Peter Chen
2025-03-05 11:04:44 -05:00
committed by GitHub
parent 5d2694d36c
commit 8a08c5e6ce
7 changed files with 527 additions and 26 deletions

View File

@@ -902,6 +902,26 @@ isGlobalFrozen(
return sle.isFlag(ripple::lsfGlobalFreeze);
}
bool
fetchAndCheckAnyFlagsExists(
BackendInterface const& backend,
std::uint32_t sequence,
ripple::Keylet const& keylet,
std::vector<std::uint32_t> const& flags,
boost::asio::yield_context yield
)
{
auto const blob = backend.fetchLedgerObject(keylet.key, sequence, yield);
if (!blob)
return false;
ripple::SerialIter it{blob->data(), blob->size()};
ripple::SLE const sle{it, keylet.key};
return std::ranges::any_of(flags, [sle](std::uint32_t flag) { return sle.isFlag(flag); });
}
bool
isFrozen(
BackendInterface const& backend,
@@ -915,35 +935,43 @@ isFrozen(
if (ripple::isXRP(currency))
return false;
auto key = ripple::keylet::account(issuer).key;
auto blob = backend.fetchLedgerObject(key, sequence, yield);
if (!blob)
return false;
ripple::SerialIter it{blob->data(), blob->size()};
ripple::SLE const sle{it, key};
if (sle.isFlag(ripple::lsfGlobalFreeze))
if (fetchAndCheckAnyFlagsExists(
backend, sequence, ripple::keylet::account(issuer), {ripple::lsfGlobalFreeze}, yield
))
return true;
if (issuer != account) {
key = ripple::keylet::line(account, issuer, currency).key;
blob = backend.fetchLedgerObject(key, sequence, yield);
auto const trustLineKeylet = ripple::keylet::line(account, issuer, currency);
return issuer != account &&
fetchAndCheckAnyFlagsExists(
backend,
sequence,
trustLineKeylet,
{(issuer > account) ? ripple::lsfHighFreeze : ripple::lsfLowFreeze},
yield
);
}
if (!blob)
return false;
bool
isDeepFrozen(
BackendInterface const& backend,
std::uint32_t sequence,
ripple::AccountID const& account,
ripple::Currency const& currency,
ripple::AccountID const& issuer,
boost::asio::yield_context yield
)
{
if (ripple::isXRP(currency))
return false;
ripple::SerialIter issuerIt{blob->data(), blob->size()};
ripple::SLE const issuerLine{issuerIt, key};
if (issuer == account)
return false;
auto frozen = (issuer > account) ? ripple::lsfHighFreeze : ripple::lsfLowFreeze;
auto const trustLineKeylet = ripple::keylet::line(account, issuer, currency);
if (issuerLine.isFlag(frozen))
return true;
}
return false;
return fetchAndCheckAnyFlagsExists(
backend, sequence, trustLineKeylet, {ripple::lsfHighDeepFreeze, ripple::lsfLowDeepFreeze}, yield
);
}
bool
@@ -1040,7 +1068,9 @@ ammAccountHolds(
ripple::SerialIter it{blob->data(), blob->size()};
ripple::SLE const sle{it, key};
if (zeroIfFrozen && isFrozen(backend, sequence, account, currency, issuer, yield)) {
if (zeroIfFrozen &&
(isFrozen(backend, sequence, account, currency, issuer, yield) ||
isDeepFrozen(backend, sequence, account, currency, issuer, yield))) {
amount.setIssue(ripple::Issue(currency, issuer));
amount.clear();
} else {

View File

@@ -428,6 +428,49 @@ isFrozen(
boost::asio::yield_context yield
);
/**
* @brief Fetches a ledger object and checks if any of the specified flag is set on the account.
*
* @param backend The backend to use
* @param sequence The sequence
* @param keylet The keylet representing the object
* @param flags The flags to check on the fetched `SLE`.
* @param yield The coroutine context
* @return true if any of the flag in flags are set for this account; false otherwise
*/
bool
fetchAndCheckAnyFlagsExists(
BackendInterface const& backend,
std::uint32_t sequence,
ripple::Keylet const& keylet,
std::vector<std::uint32_t> const& flags,
boost::asio::yield_context yield
);
/**
* @brief Whether the trustline is deep frozen.
*
* For deep freeze, (unlike regular freeze) we do not care which account has the high/low deep freeze flag.
* We only care about if the trustline is deep frozen or not.
*
* @param backend The backend to use
* @param sequence The sequence
* @param account The account
* @param currency The currency
* @param issuer The issuer
* @param yield The coroutine context
* @return true if the account is deep frozen; false otherwise
*/
bool
isDeepFrozen(
BackendInterface const& backend,
std::uint32_t sequence,
ripple::AccountID const& account,
ripple::Currency const& currency,
ripple::AccountID const& issuer,
boost::asio::yield_context yield
);
/**
* @brief Whether the account that owns a LPToken is frozen for the assets in the pool
*

View File

@@ -86,6 +86,8 @@ AccountLinesHandler::addLine(
bool const lineNoRipplePeer = (flags & (not viewLowest ? ripple::lsfLowNoRipple : ripple::lsfHighNoRipple)) != 0u;
bool const lineFreeze = (flags & (viewLowest ? ripple::lsfLowFreeze : ripple::lsfHighFreeze)) != 0u;
bool const lineFreezePeer = (flags & (not viewLowest ? ripple::lsfLowFreeze : ripple::lsfHighFreeze)) != 0u;
bool const lineDeepFreeze = (flags & (viewLowest ? ripple::lsfLowDeepFreeze : ripple::lsfHighFreeze)) != 0u;
bool const lineDeepFreezePeer = (flags & (not viewLowest ? ripple::lsfLowDeepFreeze : ripple::lsfHighFreeze)) != 0u;
ripple::STAmount const& saBalance = balance;
ripple::STAmount const& saLimit = lineLimit;
@@ -112,6 +114,12 @@ AccountLinesHandler::addLine(
if (lineFreezePeer)
line.freezePeer = true;
if (lineDeepFreeze)
line.deepFreeze = true;
if (lineDeepFreezePeer)
line.deepFreezePeer = true;
line.noRipple = lineNoRipple;
line.noRipplePeer = lineNoRipplePeer;
lines.push_back(line);
@@ -264,6 +272,12 @@ tag_invoke(
if (line.freezePeer)
obj[JS(freeze_peer)] = *(line.freezePeer);
if (line.deepFreeze)
obj[JS(deep_freeze)] = *(line.deepFreeze);
if (line.deepFreezePeer)
obj[JS(deep_freeze_peer)] = *(line.deepFreezePeer);
jv = std::move(obj);
}

View File

@@ -76,6 +76,8 @@ public:
std::optional<bool> peerAuthorized;
std::optional<bool> freeze;
std::optional<bool> freezePeer;
std::optional<bool> deepFreeze;
std::optional<bool> deepFreezePeer;
};
/**