mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-27 15:15:52 +00:00
@@ -81,6 +81,34 @@ struct Status
|
|||||||
return *err != RippledError::rpcSUCCESS;
|
return *err != RippledError::rpcSUCCESS;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the Status contains the desired @ref RippledError
|
||||||
|
*
|
||||||
|
* @param other The RippledError to match
|
||||||
|
* @return bool true if status matches given error; false otherwise
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
operator==(RippledError other) const
|
||||||
|
{
|
||||||
|
if (auto err = std::get_if<RippledError>(&code))
|
||||||
|
return *err == other;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the Status contains the desired @ref ClioError
|
||||||
|
*
|
||||||
|
* @param other The RippledError to match
|
||||||
|
* @return bool true if status matches given error; false otherwise
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
operator==(ClioError other) const
|
||||||
|
{
|
||||||
|
if (auto err = std::get_if<ClioError>(&code))
|
||||||
|
return *err == other;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ buildResponse(Context const& ctx)
|
|||||||
if (auto object = get_if<boost::json::object>(&v);
|
if (auto object = get_if<boost::json::object>(&v);
|
||||||
object && not shouldSuppressValidatedFlag(ctx))
|
object && not shouldSuppressValidatedFlag(ctx))
|
||||||
{
|
{
|
||||||
(*object)["validated"] = true;
|
(*object)[JS(validated)] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
|||||||
@@ -73,13 +73,13 @@ struct AccountCursor
|
|||||||
std::uint32_t hint;
|
std::uint32_t hint;
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
toString()
|
toString() const
|
||||||
{
|
{
|
||||||
return ripple::strHex(index) + "," + std::to_string(hint);
|
return ripple::strHex(index) + "," + std::to_string(hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isNonZero()
|
isNonZero() const
|
||||||
{
|
{
|
||||||
return index.isNonZero() || hint != 0;
|
return index.isNonZero() || hint != 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,35 +81,11 @@ getRequiredUInt(boost::json::object const& request, std::string const& field)
|
|||||||
throw InvalidParamsError("Missing field " + field);
|
throw InvalidParamsError("Missing field " + field);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
isOwnedByAccount(ripple::SLE const& sle, ripple::AccountID const& accountID)
|
|
||||||
{
|
|
||||||
if (sle.getType() == ripple::ltRIPPLE_STATE)
|
|
||||||
{
|
|
||||||
return (sle.getFieldAmount(ripple::sfLowLimit).getIssuer() ==
|
|
||||||
accountID) ||
|
|
||||||
(sle.getFieldAmount(ripple::sfHighLimit).getIssuer() == accountID);
|
|
||||||
}
|
|
||||||
else if (sle.isFieldPresent(ripple::sfAccount))
|
|
||||||
{
|
|
||||||
return sle.getAccountID(ripple::sfAccount) == accountID;
|
|
||||||
}
|
|
||||||
else if (sle.getType() == ripple::ltSIGNER_LIST)
|
|
||||||
{
|
|
||||||
ripple::Keylet const accountSignerList =
|
|
||||||
ripple::keylet::signers(accountID);
|
|
||||||
return sle.key() == accountSignerList.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<AccountCursor>
|
std::optional<AccountCursor>
|
||||||
parseAccountCursor(
|
parseAccountCursor(
|
||||||
BackendInterface const& backend,
|
BackendInterface const& backend,
|
||||||
std::uint32_t seq,
|
std::uint32_t seq,
|
||||||
std::optional<std::string> jsonCursor,
|
std::optional<std::string> jsonCursor,
|
||||||
ripple::AccountID const& accountID,
|
|
||||||
boost::asio::yield_context& yield)
|
boost::asio::yield_context& yield)
|
||||||
{
|
{
|
||||||
ripple::uint256 cursorIndex = beast::zero;
|
ripple::uint256 cursorIndex = beast::zero;
|
||||||
@@ -140,19 +116,6 @@ parseAccountCursor(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// We then must check if the object pointed to by the marker is actually
|
|
||||||
// owned by the account in the request.
|
|
||||||
auto const ownedNode = backend.fetchLedgerObject(cursorIndex, seq, yield);
|
|
||||||
|
|
||||||
if (!ownedNode)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
ripple::SerialIter it{ownedNode->data(), ownedNode->size()};
|
|
||||||
ripple::SLE sle{it, cursorIndex};
|
|
||||||
|
|
||||||
if (!isOwnedByAccount(sle, accountID))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return AccountCursor({cursorIndex, startHint});
|
return AccountCursor({cursorIndex, startHint});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,13 +626,11 @@ traverseOwnedNodes(
|
|||||||
ripple::keylet::account(accountID).key, sequence, yield))
|
ripple::keylet::account(accountID).key, sequence, yield))
|
||||||
return Status{RippledError::rpcACT_NOT_FOUND};
|
return Status{RippledError::rpcACT_NOT_FOUND};
|
||||||
|
|
||||||
auto parsedCursor =
|
auto maybeCursor = parseAccountCursor(backend, sequence, jsonCursor, yield);
|
||||||
parseAccountCursor(backend, sequence, jsonCursor, accountID, yield);
|
if (!maybeCursor)
|
||||||
|
|
||||||
if (!parsedCursor)
|
|
||||||
return Status(ripple::rpcINVALID_PARAMS, "Malformed cursor");
|
return Status(ripple::rpcINVALID_PARAMS, "Malformed cursor");
|
||||||
|
|
||||||
auto [hexCursor, startHint] = *parsedCursor;
|
auto [hexCursor, startHint] = *maybeCursor;
|
||||||
|
|
||||||
return traverseOwnedNodes(
|
return traverseOwnedNodes(
|
||||||
backend,
|
backend,
|
||||||
@@ -715,22 +676,21 @@ traverseOwnedNodes(
|
|||||||
auto hintDir =
|
auto hintDir =
|
||||||
backend.fetchLedgerObject(hintIndex.key, sequence, yield);
|
backend.fetchLedgerObject(hintIndex.key, sequence, yield);
|
||||||
|
|
||||||
if (hintDir)
|
if (!hintDir)
|
||||||
{
|
return Status(ripple::rpcINVALID_PARAMS, "Invalid marker");
|
||||||
|
|
||||||
ripple::SerialIter it{hintDir->data(), hintDir->size()};
|
ripple::SerialIter it{hintDir->data(), hintDir->size()};
|
||||||
ripple::SLE sle{it, hintIndex.key};
|
ripple::SLE sle{it, hintIndex.key};
|
||||||
|
|
||||||
for (auto const& key : sle.getFieldV256(ripple::sfIndexes))
|
if (auto const& indexes = sle.getFieldV256(ripple::sfIndexes);
|
||||||
|
std::find(std::begin(indexes), std::end(indexes), hexMarker) ==
|
||||||
|
std::end(indexes))
|
||||||
{
|
{
|
||||||
if (key == hexMarker)
|
// result in empty dataset
|
||||||
{
|
return AccountCursor({beast::zero, 0});
|
||||||
// We found the hint, we can start here
|
|
||||||
currentIndex = hintIndex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentIndex = hintIndex;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ parseAccountCursor(
|
|||||||
BackendInterface const& backend,
|
BackendInterface const& backend,
|
||||||
std::uint32_t seq,
|
std::uint32_t seq,
|
||||||
std::optional<std::string> jsonCursor,
|
std::optional<std::string> jsonCursor,
|
||||||
ripple::AccountID const& accountID,
|
|
||||||
boost::asio::yield_context& yield);
|
boost::asio::yield_context& yield);
|
||||||
|
|
||||||
// TODO this function should probably be in a different file and namespace
|
// TODO this function should probably be in a different file and namespace
|
||||||
|
|||||||
@@ -202,8 +202,7 @@ doAccountObjects(Context const& context)
|
|||||||
if (auto status = std::get_if<RPC::Status>(&next))
|
if (auto status = std::get_if<RPC::Status>(&next))
|
||||||
return *status;
|
return *status;
|
||||||
|
|
||||||
auto nextMarker = std::get<RPC::AccountCursor>(next);
|
auto const& nextMarker = std::get<RPC::AccountCursor>(next);
|
||||||
|
|
||||||
if (nextMarker.isNonZero())
|
if (nextMarker.isNonZero())
|
||||||
response[JS(marker)] = nextMarker.toString();
|
response[JS(marker)] = nextMarker.toString();
|
||||||
|
|
||||||
|
|||||||
@@ -442,8 +442,7 @@ doUnsubscribe(Context const& context)
|
|||||||
if (request.contains("books"))
|
if (request.contains("books"))
|
||||||
unsubscribeToBooks(books, context.session, *context.subscriptions);
|
unsubscribeToBooks(books, context.session, *context.subscriptions);
|
||||||
|
|
||||||
boost::json::object response = {{"status", "success"}};
|
return boost::json::object{};
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace RPC
|
} // namespace RPC
|
||||||
|
|||||||
Reference in New Issue
Block a user