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