rippled
Loading...
Searching...
No Matches
AccountLines.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2014 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/paths/TrustLine.h>
21#include <xrpld/ledger/ReadView.h>
22#include <xrpld/rpc/Context.h>
23#include <xrpld/rpc/detail/RPCHelpers.h>
24#include <xrpld/rpc/detail/Tuning.h>
25
26#include <xrpl/protocol/ErrorCodes.h>
27#include <xrpl/protocol/RPCErr.h>
28#include <xrpl/protocol/jss.h>
29#include <xrpl/resource/Fees.h>
30
31namespace ripple {
32
33void
34addLine(Json::Value& jsonLines, RPCTrustLine const& line)
35{
36 STAmount const& saBalance(line.getBalance());
37 STAmount const& saLimit(line.getLimit());
38 STAmount const& saLimitPeer(line.getLimitPeer());
39 Json::Value& jPeer(jsonLines.append(Json::objectValue));
40
41 jPeer[jss::account] = to_string(line.getAccountIDPeer());
42 // Amount reported is positive if current account holds other
43 // account's IOUs.
44 //
45 // Amount reported is negative if other account holds current
46 // account's IOUs.
47 jPeer[jss::balance] = saBalance.getText();
48 jPeer[jss::currency] = to_string(saBalance.issue().currency);
49 jPeer[jss::limit] = saLimit.getText();
50 jPeer[jss::limit_peer] = saLimitPeer.getText();
51 jPeer[jss::quality_in] = line.getQualityIn().value;
52 jPeer[jss::quality_out] = line.getQualityOut().value;
53 if (line.getAuth())
54 jPeer[jss::authorized] = true;
55 if (line.getAuthPeer())
56 jPeer[jss::peer_authorized] = true;
57 if (line.getNoRipple())
58 jPeer[jss::no_ripple] = true;
59 if (line.getNoRipplePeer())
60 jPeer[jss::no_ripple_peer] = true;
61 if (line.getFreeze())
62 jPeer[jss::freeze] = true;
63 if (line.getFreezePeer())
64 jPeer[jss::freeze_peer] = true;
65 if (line.getDeepFreeze())
66 jPeer[jss::deep_freeze] = true;
67 if (line.getDeepFreezePeer())
68 jPeer[jss::deep_freeze_peer] = true;
69}
70
71// {
72// account: <account>
73// ledger_hash : <ledger>
74// ledger_index : <ledger_index>
75// limit: integer // optional
76// marker: opaque // optional, resume previous query
77// ignore_default: bool // do not return lines in default state (on
78// this account's side)
79// }
82{
83 auto const& params(context.params);
84 if (!params.isMember(jss::account))
85 return RPC::missing_field_error(jss::account);
86
87 if (!params[jss::account].isString())
88 return RPC::invalid_field_error(jss::account);
89
91 auto result = RPC::lookupLedger(ledger, context);
92 if (!ledger)
93 return result;
94
95 auto id = parseBase58<AccountID>(params[jss::account].asString());
96 if (!id)
97 {
99 return result;
100 }
101 auto const accountID{std::move(id.value())};
102
103 if (!ledger->exists(keylet::account(accountID)))
105
106 std::string strPeer;
107 if (params.isMember(jss::peer))
108 strPeer = params[jss::peer].asString();
109
110 auto const raPeerAccount = [&]() -> std::optional<AccountID> {
111 return strPeer.empty() ? std::nullopt : parseBase58<AccountID>(strPeer);
112 }();
113 if (!strPeer.empty() && !raPeerAccount)
114 {
116 return result;
117 }
118
119 unsigned int limit;
120 if (auto err = readLimitField(limit, RPC::Tuning::accountLines, context))
121 return *err;
122
123 if (limit == 0)
125
126 // this flag allows the requester to ask incoming trustlines in default
127 // state be omitted
128 bool ignoreDefault = params.isMember(jss::ignore_default) &&
129 params[jss::ignore_default].asBool();
130
131 Json::Value& jsonLines(result[jss::lines] = Json::arrayValue);
132 struct VisitData
133 {
135 AccountID const& accountID;
136 std::optional<AccountID> const& raPeerAccount;
137 bool ignoreDefault;
138 uint32_t foundCount;
139 };
140 VisitData visitData = {{}, accountID, raPeerAccount, ignoreDefault, 0};
141 uint256 startAfter = beast::zero;
142 std::uint64_t startHint = 0;
143
144 if (params.isMember(jss::marker))
145 {
146 if (!params[jss::marker].isString())
147 return RPC::expected_field_error(jss::marker, "string");
148
149 // Marker is composed of a comma separated index and start hint. The
150 // former will be read as hex, and the latter using boost lexical cast.
151 std::stringstream marker(params[jss::marker].asString());
152 std::string value;
153 if (!std::getline(marker, value, ','))
155
156 if (!startAfter.parseHex(value))
158
159 if (!std::getline(marker, value, ','))
161
162 try
163 {
164 startHint = boost::lexical_cast<std::uint64_t>(value);
165 }
166 catch (boost::bad_lexical_cast&)
167 {
169 }
170
171 // We then must check if the object pointed to by the marker is actually
172 // owned by the account in the request.
173 auto const sle = ledger->read({ltANY, startAfter});
174
175 if (!sle)
177
178 if (!RPC::isRelatedToAccount(*ledger, sle, accountID))
180 }
181
182 auto count = 0;
183 std::optional<uint256> marker = {};
184 std::uint64_t nextHint = 0;
185 {
186 if (!forEachItemAfter(
187 *ledger,
188 accountID,
189 startAfter,
190 startHint,
191 limit + 1,
192 [&visitData, &count, &marker, &limit, &nextHint](
193 std::shared_ptr<SLE const> const& sleCur) {
194 if (!sleCur)
195 {
196 UNREACHABLE("ripple::doAccountLines : null SLE");
197 return false;
198 }
199
200 if (++count == limit)
201 {
202 marker = sleCur->key();
203 nextHint =
204 RPC::getStartHint(sleCur, visitData.accountID);
205 }
206
207 if (sleCur->getType() != ltRIPPLE_STATE)
208 return true;
209
210 bool ignore = false;
211 if (visitData.ignoreDefault)
212 {
213 if (sleCur->getFieldAmount(sfLowLimit).getIssuer() ==
214 visitData.accountID)
215 ignore =
216 !(sleCur->getFieldU32(sfFlags) & lsfLowReserve);
217 else
218 ignore = !(
219 sleCur->getFieldU32(sfFlags) & lsfHighReserve);
220 }
221
222 if (!ignore && count <= limit)
223 {
224 auto const line =
225 RPCTrustLine::makeItem(visitData.accountID, sleCur);
226
227 if (line &&
228 (!visitData.raPeerAccount ||
229 *visitData.raPeerAccount ==
230 line->getAccountIDPeer()))
231 {
232 visitData.items.emplace_back(*line);
233 }
234 }
235
236 return true;
237 }))
238 {
240 }
241 }
242
243 // Both conditions need to be checked because marker is set on the limit-th
244 // item, but if there is no item on the limit + 1 iteration, then there is
245 // no need to return a marker.
246 if (count == limit + 1 && marker)
247 {
248 result[jss::limit] = limit;
249 result[jss::marker] =
250 to_string(*marker) + "," + std::to_string(nextHint);
251 }
252
253 result[jss::account] = toBase58(accountID);
254
255 for (auto const& item : visitData.items)
256 addLine(jsonLines, item);
257
259 return result;
260}
261
262} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:897
Currency currency
Definition: Issue.h:38
static std::optional< RPCTrustLine > makeItem(AccountID const &accountID, std::shared_ptr< SLE const > const &sle)
Definition: TrustLine.cpp:110
std::string getText() const override
Definition: STAmount.cpp:547
Issue const & issue() const
Definition: STAmount.h:487
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:503
T empty(T... args)
T getline(T... args)
@ arrayValue
array value (ordered list)
Definition: json_value.h:43
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:44
static LimitRange constexpr accountLines
Limits for the account_lines command.
Json::Value invalid_field_error(std::string const &name)
Definition: ErrorCodes.h:315
bool isRelatedToAccount(ReadView const &ledger, std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Tests if a SLE is owned by accountID.
Definition: RPCHelpers.cpp:115
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition: ErrorCodes.h:223
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:339
Status lookupLedger(std::shared_ptr< ReadView const > &ledger, JsonContext &context, Json::Value &result)
Look up a ledger from a request and fill a Json::Result with the data representing a ledger.
Definition: RPCHelpers.cpp:622
std::uint64_t getStartHint(std::shared_ptr< SLE const > const &sle, AccountID const &accountID)
Gets the start hint for traversing account objects.
Definition: RPCHelpers.cpp:98
Json::Value missing_field_error(std::string const &name)
Definition: ErrorCodes.h:273
Charge const feeMediumBurdenRPC
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:175
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:114
void addLine(Json::Value &jsonLines, RPCTrustLine const &line)
@ rpcACT_NOT_FOUND
Definition: ErrorCodes.h:70
@ rpcACT_MALFORMED
Definition: ErrorCodes.h:90
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
Json::Value doAccountLines(RPC::JsonContext &context)
@ lsfHighReserve
@ lsfLowReserve
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:31
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
@ ltANY
A special type, matching any ledger entry type.
Definition: LedgerFormats.h:78
bool forEachItemAfter(ReadView const &view, Keylet const &root, uint256 const &after, std::uint64_t const hint, unsigned int limit, std::function< bool(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items after an item in the given directory.
Definition: View.cpp:572
Resource::Charge & loadType
Definition: Context.h:42
Json::Value params
Definition: Context.h:63
T to_string(T... args)