rippled
Loading...
Searching...
No Matches
AccountInfo.cpp
1#include <xrpld/app/main/Application.h>
2#include <xrpld/app/misc/TxQ.h>
3#include <xrpld/rpc/Context.h>
4#include <xrpld/rpc/GRPCHandlers.h>
5#include <xrpld/rpc/detail/RPCHelpers.h>
6#include <xrpld/rpc/detail/RPCLedgerHelpers.h>
7
8#include <xrpl/json/json_value.h>
9#include <xrpl/ledger/ReadView.h>
10#include <xrpl/protocol/ErrorCodes.h>
11#include <xrpl/protocol/Indexes.h>
12#include <xrpl/protocol/UintTypes.h>
13#include <xrpl/protocol/jss.h>
14
15namespace ripple {
16
17// {
18// account: <ident>,
19// ledger_hash : <ledger>
20// ledger_index : <ledger_index>
21// signer_lists : <bool> // optional (default false)
22// // if true return SignerList(s).
23// queue : <bool> // optional (default false)
24// // if true return information about transactions
25// // in the current TxQ, only if the requested
26// // ledger is open. Otherwise if true, returns an
27// // error.
28// }
29
30// TODO(tom): what is that "default"?
33{
34 auto& params = context.params;
35
36 std::string strIdent;
37 if (params.isMember(jss::account))
38 {
39 if (!params[jss::account].isString())
40 return RPC::invalid_field_error(jss::account);
41 strIdent = params[jss::account].asString();
42 }
43 else if (params.isMember(jss::ident))
44 {
45 if (!params[jss::ident].isString())
46 return RPC::invalid_field_error(jss::ident);
47 strIdent = params[jss::ident].asString();
48 }
49 else
50 return RPC::missing_field_error(jss::account);
51
53 auto result = RPC::lookupLedger(ledger, context);
54
55 if (!ledger)
56 return result;
57
58 // Get info on account.
59 auto id = parseBase58<AccountID>(strIdent);
60 if (!id)
61 {
63 return result;
64 }
65 auto const accountID{std::move(id.value())};
66
67 static constexpr std::
69 lsFlags{
70 {{"defaultRipple", lsfDefaultRipple},
71 {"depositAuth", lsfDepositAuth},
72 {"disableMasterKey", lsfDisableMaster},
73 {"disallowIncomingXRP", lsfDisallowXRP},
74 {"globalFreeze", lsfGlobalFreeze},
75 {"noFreeze", lsfNoFreeze},
76 {"passwordSpent", lsfPasswordSpent},
77 {"requireAuthorization", lsfRequireAuth},
78 {"requireDestinationTag", lsfRequireDestTag}}};
79
80 static constexpr std::
82 disallowIncomingFlags{
83 {{"disallowIncomingNFTokenOffer",
85 {"disallowIncomingCheck", lsfDisallowIncomingCheck},
86 {"disallowIncomingPayChan", lsfDisallowIncomingPayChan},
87 {"disallowIncomingTrustline", lsfDisallowIncomingTrustline}}};
88
90 allowTrustLineClawbackFlag{
91 "allowTrustLineClawback", lsfAllowTrustLineClawback};
92
94 allowTrustLineLockingFlag{
95 "allowTrustLineLocking", lsfAllowTrustLineLocking};
96
97 auto const sleAccepted = ledger->read(keylet::account(accountID));
98 if (sleAccepted)
99 {
100 auto const queue =
101 params.isMember(jss::queue) && params[jss::queue].asBool();
102
103 if (queue && !ledger->open())
104 {
105 // It doesn't make sense to request the queue
106 // with any closed or validated ledger.
108 return result;
109 }
110
111 Json::Value jvAccepted(Json::objectValue);
112 RPC::injectSLE(jvAccepted, *sleAccepted);
113 result[jss::account_data] = jvAccepted;
114
116 for (auto const& lsf : lsFlags)
117 acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second);
118
119 if (ledger->rules().enabled(featureDisallowIncoming))
120 {
121 for (auto const& lsf : disallowIncomingFlags)
122 acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second);
123 }
124
125 if (ledger->rules().enabled(featureClawback))
126 acctFlags[allowTrustLineClawbackFlag.first.data()] =
127 sleAccepted->isFlag(allowTrustLineClawbackFlag.second);
128
129 if (ledger->rules().enabled(featureTokenEscrow))
130 acctFlags[allowTrustLineLockingFlag.first.data()] =
131 sleAccepted->isFlag(allowTrustLineLockingFlag.second);
132
133 result[jss::account_flags] = std::move(acctFlags);
134
135 // The document[https://xrpl.org/account_info.html#account_info] states
136 // that signer_lists is a bool, however assigning any string value
137 // works. Do not allow this. This check is for api Version 2 onwards
138 // only
139 if (context.apiVersion > 1u && params.isMember(jss::signer_lists) &&
140 !params[jss::signer_lists].isBool())
141 {
143 return result;
144 }
145
146 // Return SignerList(s) if that is requested.
147 if (params.isMember(jss::signer_lists) &&
148 params[jss::signer_lists].asBool())
149 {
150 // We put the SignerList in an array because of an anticipated
151 // future when we support multiple signer lists on one account.
152 Json::Value jvSignerList = Json::arrayValue;
153
154 // This code will need to be revisited if in the future we support
155 // multiple SignerLists on one account.
156 auto const sleSigners = ledger->read(keylet::signers(accountID));
157 if (sleSigners)
158 jvSignerList.append(sleSigners->getJson(JsonOptions::none));
159
160 // Documentation states this is returned as part of the account_info
161 // response, but previously the code put it under account_data. We
162 // can move this to the documentated location from apiVersion 2
163 // onwards.
164 if (context.apiVersion == 1)
165 {
166 result[jss::account_data][jss::signer_lists] =
167 std::move(jvSignerList);
168 }
169 else
170 {
171 result[jss::signer_lists] = std::move(jvSignerList);
172 }
173 }
174 // Return queue info if that is requested
175 if (queue)
176 {
177 Json::Value jvQueueData = Json::objectValue;
178
179 auto const txs = context.app.getTxQ().getAccountTxs(accountID);
180 if (!txs.empty())
181 {
182 jvQueueData[jss::txn_count] =
183 static_cast<Json::UInt>(txs.size());
184
185 auto& jvQueueTx = jvQueueData[jss::transactions];
186 jvQueueTx = Json::arrayValue;
187
188 std::uint32_t seqCount = 0;
189 std::uint32_t ticketCount = 0;
192 std::optional<std::uint32_t> lowestTicket;
193 std::optional<std::uint32_t> highestTicket;
194 bool anyAuthChanged = false;
195 XRPAmount totalSpend(0);
196
197 // We expect txs to be returned sorted by SeqProxy. Verify
198 // that with a couple of asserts.
199 SeqProxy prevSeqProxy = SeqProxy::sequence(0);
200 for (auto const& tx : txs)
201 {
203
204 if (tx.seqProxy.isSeq())
205 {
206 XRPL_ASSERT(
207 prevSeqProxy < tx.seqProxy,
208 "rpple::doAccountInfo : first sorted proxy");
209 prevSeqProxy = tx.seqProxy;
210 jvTx[jss::seq] = tx.seqProxy.value();
211 ++seqCount;
212 if (!lowestSeq)
213 lowestSeq = tx.seqProxy.value();
214 highestSeq = tx.seqProxy.value();
215 }
216 else
217 {
218 XRPL_ASSERT(
219 prevSeqProxy < tx.seqProxy,
220 "rpple::doAccountInfo : second sorted proxy");
221 prevSeqProxy = tx.seqProxy;
222 jvTx[jss::ticket] = tx.seqProxy.value();
223 ++ticketCount;
224 if (!lowestTicket)
225 lowestTicket = tx.seqProxy.value();
226 highestTicket = tx.seqProxy.value();
227 }
228
229 jvTx[jss::fee_level] = to_string(tx.feeLevel);
230 if (tx.lastValid)
231 jvTx[jss::LastLedgerSequence] = *tx.lastValid;
232
233 jvTx[jss::fee] = to_string(tx.consequences.fee());
234 auto const spend = tx.consequences.potentialSpend() +
235 tx.consequences.fee();
236 jvTx[jss::max_spend_drops] = to_string(spend);
237 totalSpend += spend;
238 bool const authChanged = tx.consequences.isBlocker();
239 if (authChanged)
240 anyAuthChanged = authChanged;
241 jvTx[jss::auth_change] = authChanged;
242
243 jvQueueTx.append(std::move(jvTx));
244 }
245
246 if (seqCount)
247 jvQueueData[jss::sequence_count] = seqCount;
248 if (ticketCount)
249 jvQueueData[jss::ticket_count] = ticketCount;
250 if (lowestSeq)
251 jvQueueData[jss::lowest_sequence] = *lowestSeq;
252 if (highestSeq)
253 jvQueueData[jss::highest_sequence] = *highestSeq;
254 if (lowestTicket)
255 jvQueueData[jss::lowest_ticket] = *lowestTicket;
256 if (highestTicket)
257 jvQueueData[jss::highest_ticket] = *highestTicket;
258
259 jvQueueData[jss::auth_change_queued] = anyAuthChanged;
260 jvQueueData[jss::max_spend_drops_total] = to_string(totalSpend);
261 }
262 else
263 jvQueueData[jss::txn_count] = 0u;
264
265 result[jss::queue_data] = std::move(jvQueueData);
266 }
267 }
268 else
269 {
270 result[jss::account] = toBase58(accountID);
272 }
273
274 return result;
275}
276
277} // namespace ripple
Represents a JSON value.
Definition json_value.h:131
Value & append(Value const &value)
Append value to array at the end.
virtual TxQ & getTxQ()=0
A type that represents either a sequence value or a ticket value.
Definition SeqProxy.h:37
static constexpr SeqProxy sequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
Definition SeqProxy.h:57
std::vector< TxDetails > getAccountTxs(AccountID const &account) const
Returns information about the transactions currently in the queue for the account.
Definition TxQ.cpp:1803
T is_same_v
@ arrayValue
array value (ordered list)
Definition json_value.h:26
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:27
unsigned int UInt
Json::Value invalid_field_error(std::string const &name)
Definition ErrorCodes.h:306
void injectSLE(Json::Value &jv, SLE const &sle)
Inject JSON describing ledger entry.
void inject_error(error_code_i code, JsonValue &json)
Add or update the json update to reflect the error code.
Definition ErrorCodes.h:214
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.
Json::Value missing_field_error(std::string const &name)
Definition ErrorCodes.h:264
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet signers(AccountID const &account) noexcept
A SignerList.
Definition Indexes.cpp:311
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
@ rpcACT_NOT_FOUND
Definition ErrorCodes.h:51
@ rpcACT_MALFORMED
Definition ErrorCodes.h:71
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:65
@ lsfRequireDestTag
@ lsfPasswordSpent
@ lsfDefaultRipple
@ lsfDisallowIncomingCheck
@ lsfAllowTrustLineClawback
@ lsfDisableMaster
@ lsfDisallowIncomingPayChan
@ lsfDisallowIncomingTrustline
@ lsfAllowTrustLineLocking
@ lsfDisallowIncomingNFTokenOffer
@ lsfGlobalFreeze
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
Json::Value doAccountInfo(RPC::JsonContext &context)
unsigned int apiVersion
Definition Context.h:30
Application & app
Definition Context.h:22
T value(T... args)