mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@@ -67,6 +68,8 @@ constexpr auto kACCOUNT2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
|
||||
constexpr auto kINDEX1 = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321";
|
||||
constexpr auto kINDEX2 = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC322";
|
||||
constexpr auto kTXN_ID = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321";
|
||||
constexpr auto kLEDGER_SEQ_OBJECT = 50;
|
||||
constexpr auto kCURRENCY = "0158415500000000C1F76FF6ECB0BAC600000000";
|
||||
constexpr auto kAMM_ACCOUNT = "rnW8FAPgpQgA6VoESnVrUVJHBdq9QAtRZs";
|
||||
constexpr auto kISSUER = "rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD";
|
||||
constexpr auto kLPTOKEN_CURRENCY = "037C35306B24AAB7FF90848206E003279AA47090";
|
||||
@@ -78,6 +81,7 @@ class RPCHelpersTest : public util::prometheus::WithPrometheus, public MockBacke
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
backend_->setRange(10, 300);
|
||||
SyncAsioContextTest::SetUp();
|
||||
}
|
||||
void
|
||||
@@ -558,6 +562,277 @@ TEST_F(RPCHelpersTest, ParseIssue)
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, FetchAndCheckAnyFlagExists_BlobDoesNotExist)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuerKey = ripple::keylet::account(account);
|
||||
|
||||
// returns empty blob
|
||||
ON_CALL(*backend_, doFetchLedgerObject(issuerKey.key, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(std::optional<Blob>{}));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
// return false: blob doesn't exist
|
||||
EXPECT_FALSE(
|
||||
fetchAndCheckAnyFlagsExists(*backend_, kLEDGER_SEQ_OBJECT, issuerKey, {ripple::lsfHighDeepFreeze}, yield)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, FetchAndCheckAnyFlagExistsBlobExists_AccountWithCorrectFlag)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuerKey = ripple::keylet::account(account);
|
||||
|
||||
// create account with highDeepFreeze Flag
|
||||
auto const accountObject = createAccountRootObject(kACCOUNT, ripple::lsfHighDeepFreeze, 1, 10, 2, kTXN_ID, 3);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(issuerKey.key, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(accountObject.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
// returns true: accountObject has the highDeepFreeze flag
|
||||
EXPECT_TRUE(
|
||||
fetchAndCheckAnyFlagsExists(*backend_, kLEDGER_SEQ_OBJECT, issuerKey, {ripple::lsfHighDeepFreeze}, yield)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, FetchAndCheckAnyFlagExistsBlobExists_AccountFlagDoesNotExist)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuerKey = ripple::keylet::account(account);
|
||||
|
||||
// create account with highDeepFreeze Flag
|
||||
auto const accountObject = createAccountRootObject(kACCOUNT, ripple::lsfLowDeepFreeze, 1, 10, 2, kTXN_ID, 3);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(issuerKey.key, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(accountObject.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
// returns false: accountObject has the lowDeepFreeze flag
|
||||
EXPECT_FALSE(
|
||||
fetchAndCheckAnyFlagsExists(*backend_, kLEDGER_SEQ_OBJECT, issuerKey, {ripple::lsfHighDeepFreeze}, yield)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isGlobalFrozen_AccountIsGlobalFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuerKey = ripple::keylet::account(account);
|
||||
|
||||
auto const accountObject = createAccountRootObject(kACCOUNT, ripple::lsfGlobalFreeze, 1, 10, 2, kTXN_ID, 3);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(issuerKey.key, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(accountObject.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
// returns false: accountObject has the lowDeepFreeze flag
|
||||
EXPECT_TRUE(isGlobalFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isDeepFrozen_TrustLineIsDeepFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const account2 = getAccountIdWithString(kACCOUNT2);
|
||||
|
||||
// create a trustline between account and account2 and is deep frozen
|
||||
auto const trustLineKey = ripple::keylet::line(account, account2, ripple::Currency{kCURRENCY}).key;
|
||||
auto const trustlineDeepFrozen = createRippleStateLedgerObject(
|
||||
"USD", kACCOUNT, 8, kACCOUNT, 1000, kACCOUNT2, 2000, kINDEX1, 2, ripple::lsfLowDeepFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustlineDeepFrozen.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
EXPECT_TRUE(isDeepFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, ripple::Currency{kCURRENCY}, account2, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isDeepFrozen_TrustLineIsNotDeepFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const account2 = getAccountIdWithString(kACCOUNT2);
|
||||
|
||||
// create a trustline between account and account2 that is frozen (NOT DeepFrozen)
|
||||
auto const trustLineKey = ripple::keylet::line(account, account2, ripple::Currency{kCURRENCY}).key;
|
||||
auto const trustlineFrozen = createRippleStateLedgerObject(
|
||||
"USD", kACCOUNT, 8, kACCOUNT, 1000, kACCOUNT2, 2000, kINDEX1, 2, ripple::lsfLowFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustlineFrozen.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
EXPECT_FALSE(isDeepFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, ripple::Currency{kCURRENCY}, account2, yield)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isDeepFrozen_IssuerAndAccountIsSameWillNotBeDeepFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
|
||||
auto const trustLineKey = ripple::keylet::line(account, issuer, ripple::Currency{kCURRENCY}).key;
|
||||
auto const trustlineDeepFrozen = createRippleStateLedgerObject(
|
||||
"USD", kACCOUNT, 8, kACCOUNT, 1000, kACCOUNT2, 2000, kINDEX1, 2, ripple::lsfLowDeepFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustlineDeepFrozen.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
// both accounts are same so trustline is not deep frozen
|
||||
EXPECT_FALSE(isDeepFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, ripple::Currency{kCURRENCY}, account, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isFrozen_IssuerAccountIsGlobalFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
|
||||
auto const accountObject = createAccountRootObject(kACCOUNT2, ripple::lsfGlobalFreeze, 1, 10, 2, kTXN_ID, 3);
|
||||
auto const issuerKey = ripple::keylet::account(issuer).key;
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(issuerKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(accountObject.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
EXPECT_TRUE(isFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, ripple::Currency{kCURRENCY}, issuer, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isFrozen_IssuerAndAccountIsSameWillNotBeFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
|
||||
auto const trustLineKey = ripple::keylet::line(account, issuer, ripple::Currency{kCURRENCY}).key;
|
||||
auto const trustlineDeepFrozen = createRippleStateLedgerObject(
|
||||
"USD", kACCOUNT, 8, kACCOUNT, 1000, kACCOUNT2, 2000, kINDEX1, 2, ripple::lsfHighFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustlineDeepFrozen.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
EXPECT_FALSE(isFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, ripple::Currency{kCURRENCY}, account, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isFrozen_IssuerTrustLineIsFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
ripple::Currency const currency{kCURRENCY};
|
||||
|
||||
auto const trustLineKey = ripple::keylet::line(account, issuer, currency).key;
|
||||
|
||||
// issuer is higher than account, so the correct flag to set is High freeze
|
||||
auto const trustlineFrozen = createRippleStateLedgerObject(
|
||||
"USD", kACCOUNT, 8, kACCOUNT, 1000, kACCOUNT2, 2000, kINDEX1, 2, ripple::lsfHighFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustlineFrozen.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
EXPECT_TRUE(isFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, currency, issuer, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, isFrozen_IssuerWithLowFreezeIsNotFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
ripple::Currency const currency{kCURRENCY};
|
||||
|
||||
auto const trustLineKey = ripple::keylet::line(account, issuer, currency).key;
|
||||
|
||||
// issuer is higher than account, but the flag set here is low freeze
|
||||
auto const trustlineFrozen = createRippleStateLedgerObject(
|
||||
"USD", kACCOUNT, 8, kACCOUNT, 1000, kACCOUNT2, 2000, kINDEX1, 2, ripple::lsfLowFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustlineFrozen.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
EXPECT_FALSE(isFrozen(*backend_, kLEDGER_SEQ_OBJECT, account, currency, issuer, yield));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, AccountHolds_TrustLineNotfrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
ripple::Currency const currency{kCURRENCY};
|
||||
|
||||
auto const trustLineKey = ripple::keylet::line(account, issuer, currency).key;
|
||||
auto const trustLine =
|
||||
createRippleStateLedgerObject(kCURRENCY, kACCOUNT2, 500, kACCOUNT, 1000, kACCOUNT2, 1000, kTXN_ID, 1, 0);
|
||||
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillOnce(Return(trustLine.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
auto const result = accountHolds(
|
||||
*backend_, *mockAmendmentCenterPtr_, kLEDGER_SEQ_OBJECT, account, currency, issuer, false, yield
|
||||
);
|
||||
// Check issuer has a balance of 500
|
||||
EXPECT_EQ(result, ripple::STAmount(getIssue(kCURRENCY, kACCOUNT2), 500));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, AccountHolds_NoTrustLine)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
ripple::Currency const currency{kCURRENCY};
|
||||
|
||||
auto const key = ripple::keylet::line(account, issuer, currency).key;
|
||||
|
||||
// return no trustline found
|
||||
EXPECT_CALL(*backend_, doFetchLedgerObject(key, kLEDGER_SEQ_OBJECT, _)).WillOnce(Return(std::nullopt));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
auto const result = accountHolds(
|
||||
*backend_, *mockAmendmentCenterPtr_, kLEDGER_SEQ_OBJECT, account, currency, issuer, false, yield
|
||||
);
|
||||
// balance is 0 as trustline is frozen
|
||||
EXPECT_EQ(result, ripple::STAmount(getIssue(kCURRENCY, kACCOUNT2), 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, AccountHolds_TrustLineButFrozen)
|
||||
{
|
||||
auto const account = getAccountIdWithString(kACCOUNT);
|
||||
auto const issuer = getAccountIdWithString(kACCOUNT2);
|
||||
ripple::Currency const currency{kCURRENCY};
|
||||
|
||||
// balance of 500, but trustline is frozen
|
||||
auto const trustLineKey = ripple::keylet::line(account, issuer, currency).key;
|
||||
|
||||
auto const trustLine = createRippleStateLedgerObject(
|
||||
kCURRENCY, kACCOUNT2, 500, kACCOUNT, 1000, kACCOUNT2, 1000, kTXN_ID, 1, ripple::lsfHighFreeze
|
||||
);
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObject(trustLineKey, kLEDGER_SEQ_OBJECT, _))
|
||||
.WillByDefault(Return(trustLine.getSerializer().peekData()));
|
||||
|
||||
runSpawn([&](boost::asio::yield_context yield) {
|
||||
auto const result = accountHolds(
|
||||
*backend_, *mockAmendmentCenterPtr_, kLEDGER_SEQ_OBJECT, account, currency, issuer, true, yield
|
||||
);
|
||||
EXPECT_EQ(result, ripple::STAmount(getIssue(kCURRENCY, kACCOUNT2), 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCHelpersTest, AccountHoldsFixLPTAmendmentDisabled)
|
||||
{
|
||||
auto ammAccount = getAccountIdWithString(kAMM_ACCOUNT);
|
||||
|
||||
@@ -739,7 +739,8 @@ TEST_F(RPCAccountLinesHandlerTest, OptionalResponseField)
|
||||
"no_ripple": false,
|
||||
"no_ripple_peer": true,
|
||||
"peer_authorized": true,
|
||||
"freeze_peer": true
|
||||
"freeze_peer": true,
|
||||
"deep_freeze_peer": true
|
||||
},
|
||||
{
|
||||
"account": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun",
|
||||
@@ -752,7 +753,8 @@ TEST_F(RPCAccountLinesHandlerTest, OptionalResponseField)
|
||||
"no_ripple": true,
|
||||
"no_ripple_peer": false,
|
||||
"authorized": true,
|
||||
"freeze": true
|
||||
"freeze": true,
|
||||
"deep_freeze": true
|
||||
}
|
||||
]
|
||||
})";
|
||||
@@ -783,12 +785,14 @@ TEST_F(RPCAccountLinesHandlerTest, OptionalResponseField)
|
||||
line1.setFlag(ripple::lsfHighAuth);
|
||||
line1.setFlag(ripple::lsfHighNoRipple);
|
||||
line1.setFlag(ripple::lsfHighFreeze);
|
||||
line1.setFlag(ripple::lsfHighDeepFreeze);
|
||||
bbs.push_back(line1.getSerializer().peekData());
|
||||
|
||||
auto line2 = createRippleStateLedgerObject("USD", kACCOUNT2, 20, kACCOUNT, 200, kACCOUNT2, 400, kTXN_ID, 0);
|
||||
line2.setFlag(ripple::lsfLowAuth);
|
||||
line2.setFlag(ripple::lsfLowNoRipple);
|
||||
line2.setFlag(ripple::lsfLowFreeze);
|
||||
line2.setFlag(ripple::lsfLowDeepFreeze);
|
||||
bbs.push_back(line2.getSerializer().peekData());
|
||||
|
||||
ON_CALL(*backend_, doFetchLedgerObjects).WillByDefault(Return(bbs));
|
||||
|
||||
@@ -1156,6 +1156,71 @@ generateNormalPathBookOffersTestBundles()
|
||||
},
|
||||
.ledgerObjectCalls = 6,
|
||||
.mockedOffers = std::vector<ripple::STObject>{gets10USDPays20XRPOffer},
|
||||
.expectedJson = fmt::format(
|
||||
R"({{
|
||||
"ledger_hash":"{}",
|
||||
"ledger_index":300,
|
||||
"offers":
|
||||
[
|
||||
{{
|
||||
"Account":"{}",
|
||||
"BookDirectory":"{}",
|
||||
"BookNode":"0",
|
||||
"Flags":0,
|
||||
"LedgerEntryType":"Offer",
|
||||
"OwnerNode":"0",
|
||||
"PreviousTxnID":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"PreviousTxnLgrSeq":0,
|
||||
"Sequence":0,
|
||||
"TakerPays":"20",
|
||||
"TakerGets":{{
|
||||
"currency":"USD",
|
||||
"issuer":"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value":"10"
|
||||
}},
|
||||
"index":"E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321",
|
||||
"owner_funds":"{}",
|
||||
"quality":"{}",
|
||||
"taker_gets_funded":{{
|
||||
"currency":"USD",
|
||||
"issuer":"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value":"0"
|
||||
}},
|
||||
"taker_pays_funded":"0"
|
||||
}}
|
||||
]
|
||||
}})",
|
||||
kLEDGER_HASH,
|
||||
kACCOUNT2,
|
||||
kPAYS20_XRP_GETS10_USD_BOOK_DIR,
|
||||
0,
|
||||
2
|
||||
),
|
||||
},
|
||||
BookOffersNormalTestBundle{
|
||||
.testName = "PaysXRPGetsUSDIsDeepFrozen",
|
||||
.inputJson = paysXRPGetsUSDInputJson,
|
||||
// prepare offer dir index
|
||||
.mockedSuccessors =
|
||||
std::map<ripple::uint256, std::optional<ripple::uint256>>{
|
||||
{getsUSDPaysXRPBook, ripple::uint256{kPAYS20_XRP_GETS10_USD_BOOK_DIR}},
|
||||
{ripple::uint256{kPAYS20_XRP_GETS10_USD_BOOK_DIR}, std::optional<ripple::uint256>{}}
|
||||
},
|
||||
.mockedLedgerObjects =
|
||||
std::map<ripple::uint256, ripple::Blob>{
|
||||
// book dir object
|
||||
{ripple::uint256{kPAYS20_XRP_GETS10_USD_BOOK_DIR},
|
||||
createOwnerDirLedgerObject({ripple::uint256{kINDEX2}}, kINDEX1).getSerializer().peekData()},
|
||||
// gets issuer account object, is deep frozen so unfunded
|
||||
{ripple::keylet::account(account).key,
|
||||
createAccountRootObject(
|
||||
kACCOUNT, ripple::lsfLowDeepFreeze, 2, 200, 2, kINDEX1, 2, kTRANSFER_RATE_X2
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()},
|
||||
},
|
||||
.ledgerObjectCalls = 4,
|
||||
.mockedOffers = std::vector<ripple::STObject>{gets10USDPays20XRPOffer},
|
||||
.expectedJson = fmt::format(
|
||||
R"({{
|
||||
"ledger_hash":"{}",
|
||||
@@ -1197,6 +1262,74 @@ generateNormalPathBookOffersTestBundles()
|
||||
2
|
||||
)
|
||||
},
|
||||
BookOffersNormalTestBundle{
|
||||
.testName = "PaysXRPGetsUSDTrustLineFrozenAndIsDeepFrozen",
|
||||
.inputJson = paysXRPGetsUSDInputJson,
|
||||
// prepare offer dir index
|
||||
.mockedSuccessors =
|
||||
std::map<ripple::uint256, std::optional<ripple::uint256>>{
|
||||
{getsUSDPaysXRPBook, ripple::uint256{kPAYS20_XRP_GETS10_USD_BOOK_DIR}},
|
||||
{ripple::uint256{kPAYS20_XRP_GETS10_USD_BOOK_DIR}, std::optional<ripple::uint256>{}}
|
||||
},
|
||||
.mockedLedgerObjects =
|
||||
std::map<ripple::uint256, ripple::Blob>{
|
||||
// book dir object
|
||||
{ripple::uint256{kPAYS20_XRP_GETS10_USD_BOOK_DIR},
|
||||
createOwnerDirLedgerObject({ripple::uint256{kINDEX2}}, kINDEX1).getSerializer().peekData()},
|
||||
// gets issuer account object, is deep frozen so unfunded
|
||||
{ripple::keylet::account(account).key,
|
||||
createAccountRootObject(
|
||||
kACCOUNT, ripple::lsfLowDeepFreeze, 2, 200, 2, kINDEX1, 2, kTRANSFER_RATE_X2
|
||||
)
|
||||
.getSerializer()
|
||||
.peekData()},
|
||||
{ripple::keylet::line(account2, account, ripple::to_currency("USD")).key,
|
||||
frozenTrustLine.getSerializer().peekData()},
|
||||
|
||||
},
|
||||
.ledgerObjectCalls = 6,
|
||||
.mockedOffers = std::vector<ripple::STObject>{gets10USDPays20XRPOffer},
|
||||
.expectedJson = fmt::format(
|
||||
R"({{
|
||||
"ledger_hash":"{}",
|
||||
"ledger_index":300,
|
||||
"offers":
|
||||
[
|
||||
{{
|
||||
"Account":"{}",
|
||||
"BookDirectory":"{}",
|
||||
"BookNode":"0",
|
||||
"Flags":0,
|
||||
"LedgerEntryType":"Offer",
|
||||
"OwnerNode":"0",
|
||||
"PreviousTxnID":"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"PreviousTxnLgrSeq":0,
|
||||
"Sequence":0,
|
||||
"TakerPays":"20",
|
||||
"TakerGets":{{
|
||||
"currency":"USD",
|
||||
"issuer":"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value":"10"
|
||||
}},
|
||||
"index":"E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321",
|
||||
"owner_funds":"{}",
|
||||
"quality":"{}",
|
||||
"taker_gets_funded":{{
|
||||
"currency":"USD",
|
||||
"issuer":"rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value":"0"
|
||||
}},
|
||||
"taker_pays_funded":"0"
|
||||
}}
|
||||
]
|
||||
}})",
|
||||
kLEDGER_HASH,
|
||||
kACCOUNT2,
|
||||
kPAYS20_XRP_GETS10_USD_BOOK_DIR,
|
||||
0,
|
||||
2
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user