Skip to content

Commit

Permalink
feat: Add support for deep freeze (#1875)
Browse files Browse the repository at this point in the history
fixes #1826
  • Loading branch information
PeterChen13579 authored Mar 5, 2025
1 parent 5d2694d commit 8a08c5e
Show file tree
Hide file tree
Showing 7 changed files with 527 additions and 26 deletions.
78 changes: 54 additions & 24 deletions src/rpc/RPCHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);

if (!blob)
return false;
auto const trustLineKeylet = ripple::keylet::line(account, issuer, currency);
return issuer != account &&
fetchAndCheckAnyFlagsExists(
backend,
sequence,
trustLineKeylet,
{(issuer > account) ? ripple::lsfHighFreeze : ripple::lsfLowFreeze},
yield
);
}

ripple::SerialIter issuerIt{blob->data(), blob->size()};
ripple::SLE const issuerLine{issuerIt, key};
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;

auto frozen = (issuer > account) ? ripple::lsfHighFreeze : ripple::lsfLowFreeze;
if (issuer == account)
return false;

if (issuerLine.isFlag(frozen))
return true;
}
auto const trustLineKeylet = ripple::keylet::line(account, issuer, currency);

return false;
return fetchAndCheckAnyFlagsExists(
backend, sequence, trustLineKeylet, {ripple::lsfHighDeepFreeze, ripple::lsfLowDeepFreeze}, yield
);
}

bool
Expand Down Expand Up @@ -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 {
Expand Down
43 changes: 43 additions & 0 deletions src/rpc/RPCHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
14 changes: 14 additions & 0 deletions src/rpc/handlers/AccountLines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down
2 changes: 2 additions & 0 deletions src/rpc/handlers/AccountLines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class AccountLinesHandler {
std::optional<bool> peerAuthorized;
std::optional<bool> freeze;
std::optional<bool> freezePeer;
std::optional<bool> deepFreeze;
std::optional<bool> deepFreezePeer;
};

/**
Expand Down
Loading

0 comments on commit 8a08c5e

Please sign in to comment.