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  // Return SignerList(s) if that is requested.
129  if (params.isMember(jss::signer_lists) &&
130  params[jss::signer_lists].asBool())
131  {
132  // We put the SignerList in an array because of an anticipated
133  // future when we support multiple signer lists on one account.
134  Json::Value jvSignerList = Json::arrayValue;
135 
136  // This code will need to be revisited if in the future we support
137  // multiple SignerLists on one account.
138  auto const sleSigners = ledger->read(keylet::signers(accountID));
139  if (sleSigners)
140  jvSignerList.append(sleSigners->getJson(JsonOptions::none));
141 
142  // Documentation states this is returned as part of the account_info
143  // response, but previously the code put it under account_data. We
144  // can move this to the documentated location from apiVersion 2
145  // onwards.
146  if (context.apiVersion == 1)
147  {
148  result[jss::account_data][jss::signer_lists] =
149  std::move(jvSignerList);
150  }
151  else
152  {
153  result[jss::signer_lists] = std::move(jvSignerList);
154  }
155  }
156  // Return queue info if that is requested
157  if (queue)
158  {
159  Json::Value jvQueueData = Json::objectValue;
160 
161  auto const txs = context.app.getTxQ().getAccountTxs(accountID);
162  if (!txs.empty())
163  {
164  jvQueueData[jss::txn_count] =
165  static_cast<Json::UInt>(txs.size());
166 
167  auto& jvQueueTx = jvQueueData[jss::transactions];
168  jvQueueTx = Json::arrayValue;
169 
170  std::uint32_t seqCount = 0;
171  std::uint32_t ticketCount = 0;
173  std::optional<std::uint32_t> highestSeq;
174  std::optional<std::uint32_t> lowestTicket;
175  std::optional<std::uint32_t> highestTicket;
176  bool anyAuthChanged = false;
177  XRPAmount totalSpend(0);
178 
179  // We expect txs to be returned sorted by SeqProxy. Verify
180  // that with a couple of asserts.
181  SeqProxy prevSeqProxy = SeqProxy::sequence(0);
182  for (auto const& tx : txs)
183  {
185 
186  if (tx.seqProxy.isSeq())
187  {
188  assert(prevSeqProxy < tx.seqProxy);
189  prevSeqProxy = tx.seqProxy;
190  jvTx[jss::seq] = tx.seqProxy.value();
191  ++seqCount;
192  if (!lowestSeq)
193  lowestSeq = tx.seqProxy.value();
194  highestSeq = tx.seqProxy.value();
195  }
196  else
197  {
198  assert(prevSeqProxy < tx.seqProxy);
199  prevSeqProxy = tx.seqProxy;
200  jvTx[jss::ticket] = tx.seqProxy.value();
201  ++ticketCount;
202  if (!lowestTicket)
203  lowestTicket = tx.seqProxy.value();
204  highestTicket = tx.seqProxy.value();
205  }
206 
207  jvTx[jss::fee_level] = to_string(tx.feeLevel);
208  if (tx.lastValid)
209  jvTx[jss::LastLedgerSequence] = *tx.lastValid;
210 
211  jvTx[jss::fee] = to_string(tx.consequences.fee());
212  auto const spend = tx.consequences.potentialSpend() +
213  tx.consequences.fee();
214  jvTx[jss::max_spend_drops] = to_string(spend);
215  totalSpend += spend;
216  bool const authChanged = tx.consequences.isBlocker();
217  if (authChanged)
218  anyAuthChanged = authChanged;
219  jvTx[jss::auth_change] = authChanged;
220 
221  jvQueueTx.append(std::move(jvTx));
222  }
223 
224  if (seqCount)
225  jvQueueData[jss::sequence_count] = seqCount;
226  if (ticketCount)
227  jvQueueData[jss::ticket_count] = ticketCount;
228  if (lowestSeq)
229  jvQueueData[jss::lowest_sequence] = *lowestSeq;
230  if (highestSeq)
231  jvQueueData[jss::highest_sequence] = *highestSeq;
232  if (lowestTicket)
233  jvQueueData[jss::lowest_ticket] = *lowestTicket;
234  if (highestTicket)
235  jvQueueData[jss::highest_ticket] = *highestTicket;
236 
237  jvQueueData[jss::auth_change_queued] = anyAuthChanged;
238  jvQueueData[jss::max_spend_drops_total] = to_string(totalSpend);
239  }
240  else
241  jvQueueData[jss::txn_count] = 0u;
242 
243  result[jss::queue_data] = std::move(jvQueueData);
244  }
245  }
246  else
247  {
248  result[jss::account] = toBase58(accountID);
250  }
251 
252  return result;
253 }
254 
255 } // 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