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 // strict: <bool> // optional (default false)
38 // // if true only allow public keys and addresses.
39 // ledger_hash : <ledger>
40 // ledger_index : <ledger_index>
41 // signer_lists : <bool> // optional (default false)
42 // // if true return SignerList(s).
43 // queue : <bool> // optional (default false)
44 // // if true return information about transactions
45 // // in the current TxQ, only if the requested
46 // // ledger is open. Otherwise if true, returns an
47 // // error.
48 // }
49 
50 // TODO(tom): what is that "default"?
53 {
54  auto& params = context.params;
55 
56  std::string strIdent;
57  if (params.isMember(jss::account))
58  strIdent = params[jss::account].asString();
59  else if (params.isMember(jss::ident))
60  strIdent = params[jss::ident].asString();
61  else
62  return RPC::missing_field_error(jss::account);
63 
65  auto result = RPC::lookupLedger(ledger, context);
66 
67  if (!ledger)
68  return result;
69 
70  bool bStrict = params.isMember(jss::strict) && params[jss::strict].asBool();
71  AccountID accountID;
72 
73  // Get info on account.
74 
75  auto jvAccepted = RPC::accountFromString(accountID, strIdent, bStrict);
76 
77  if (jvAccepted)
78  return jvAccepted;
79 
80  static constexpr std::
81  array<std::pair<std::string_view, LedgerSpecificFlags>, 9>
82  lsFlags{
83  {{"defaultRipple", lsfDefaultRipple},
84  {"depositAuth", lsfDepositAuth},
85  {"disableMasterKey", lsfDisableMaster},
86  {"disallowIncomingXRP", lsfDisallowXRP},
87  {"globalFreeze", lsfGlobalFreeze},
88  {"noFreeze", lsfNoFreeze},
89  {"passwordSpent", lsfPasswordSpent},
90  {"requireAuthorization", lsfRequireAuth},
91  {"requireDestinationTag", lsfRequireDestTag}}};
92 
93  static constexpr std::
94  array<std::pair<std::string_view, LedgerSpecificFlags>, 4>
95  disallowIncomingFlags{
96  {{"disallowIncomingNFTokenOffer",
98  {"disallowIncomingCheck", lsfDisallowIncomingCheck},
99  {"disallowIncomingPayChan", lsfDisallowIncomingPayChan},
100  {"disallowIncomingTrustline", lsfDisallowIncomingTrustline}}};
101 
102  auto const sleAccepted = ledger->read(keylet::account(accountID));
103  if (sleAccepted)
104  {
105  auto const queue =
106  params.isMember(jss::queue) && params[jss::queue].asBool();
107 
108  if (queue && !ledger->open())
109  {
110  // It doesn't make sense to request the queue
111  // with any closed or validated ledger.
113  return result;
114  }
115 
116  RPC::injectSLE(jvAccepted, *sleAccepted);
117  result[jss::account_data] = jvAccepted;
118 
119  Json::Value acctFlags{Json::objectValue};
120  for (auto const& lsf : lsFlags)
121  acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second);
122 
123  if (ledger->rules().enabled(featureDisallowIncoming))
124  {
125  for (auto const& lsf : disallowIncomingFlags)
126  acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second);
127  }
128  result[jss::account_flags] = std::move(acctFlags);
129 
130  // Return SignerList(s) if that is requested.
131  if (params.isMember(jss::signer_lists) &&
132  params[jss::signer_lists].asBool())
133  {
134  // We put the SignerList in an array because of an anticipated
135  // future when we support multiple signer lists on one account.
136  Json::Value jvSignerList = Json::arrayValue;
137 
138  // This code will need to be revisited if in the future we support
139  // multiple SignerLists on one account.
140  auto const sleSigners = ledger->read(keylet::signers(accountID));
141  if (sleSigners)
142  jvSignerList.append(sleSigners->getJson(JsonOptions::none));
143 
144  // Documentation states this is returned as part of the account_info
145  // response, but previously the code put it under account_data. We
146  // can move this to the documentated location from apiVersion 2
147  // onwards.
148  if (context.apiVersion == 1)
149  {
150  result[jss::account_data][jss::signer_lists] =
151  std::move(jvSignerList);
152  }
153  else
154  {
155  result[jss::signer_lists] = std::move(jvSignerList);
156  }
157  }
158  // Return queue info if that is requested
159  if (queue)
160  {
161  Json::Value jvQueueData = Json::objectValue;
162 
163  auto const txs = context.app.getTxQ().getAccountTxs(accountID);
164  if (!txs.empty())
165  {
166  jvQueueData[jss::txn_count] =
167  static_cast<Json::UInt>(txs.size());
168 
169  auto& jvQueueTx = jvQueueData[jss::transactions];
170  jvQueueTx = Json::arrayValue;
171 
172  std::uint32_t seqCount = 0;
173  std::uint32_t ticketCount = 0;
175  std::optional<std::uint32_t> highestSeq;
176  std::optional<std::uint32_t> lowestTicket;
177  std::optional<std::uint32_t> highestTicket;
178  bool anyAuthChanged = false;
179  XRPAmount totalSpend(0);
180 
181  // We expect txs to be returned sorted by SeqProxy. Verify
182  // that with a couple of asserts.
183  SeqProxy prevSeqProxy = SeqProxy::sequence(0);
184  for (auto const& tx : txs)
185  {
187 
188  if (tx.seqProxy.isSeq())
189  {
190  assert(prevSeqProxy < tx.seqProxy);
191  prevSeqProxy = tx.seqProxy;
192  jvTx[jss::seq] = tx.seqProxy.value();
193  ++seqCount;
194  if (!lowestSeq)
195  lowestSeq = tx.seqProxy.value();
196  highestSeq = tx.seqProxy.value();
197  }
198  else
199  {
200  assert(prevSeqProxy < tx.seqProxy);
201  prevSeqProxy = tx.seqProxy;
202  jvTx[jss::ticket] = tx.seqProxy.value();
203  ++ticketCount;
204  if (!lowestTicket)
205  lowestTicket = tx.seqProxy.value();
206  highestTicket = tx.seqProxy.value();
207  }
208 
209  jvTx[jss::fee_level] = to_string(tx.feeLevel);
210  if (tx.lastValid)
211  jvTx[jss::LastLedgerSequence] = *tx.lastValid;
212 
213  jvTx[jss::fee] = to_string(tx.consequences.fee());
214  auto const spend = tx.consequences.potentialSpend() +
215  tx.consequences.fee();
216  jvTx[jss::max_spend_drops] = to_string(spend);
217  totalSpend += spend;
218  bool const authChanged = tx.consequences.isBlocker();
219  if (authChanged)
220  anyAuthChanged = authChanged;
221  jvTx[jss::auth_change] = authChanged;
222 
223  jvQueueTx.append(std::move(jvTx));
224  }
225 
226  if (seqCount)
227  jvQueueData[jss::sequence_count] = seqCount;
228  if (ticketCount)
229  jvQueueData[jss::ticket_count] = ticketCount;
230  if (lowestSeq)
231  jvQueueData[jss::lowest_sequence] = *lowestSeq;
232  if (highestSeq)
233  jvQueueData[jss::highest_sequence] = *highestSeq;
234  if (lowestTicket)
235  jvQueueData[jss::lowest_ticket] = *lowestTicket;
236  if (highestTicket)
237  jvQueueData[jss::highest_ticket] = *highestTicket;
238 
239  jvQueueData[jss::auth_change_queued] = anyAuthChanged;
240  jvQueueData[jss::max_spend_drops_total] = to_string(totalSpend);
241  }
242  else
243  jvQueueData[jss::txn_count] = 0u;
244 
245  result[jss::queue_data] = std::move(jvQueueData);
246  }
247  }
248  else
249  {
250  result[jss::account] = toBase58(accountID);
252  }
253 
254  return result;
255 }
256 
257 } // 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:52
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::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
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::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
ripple::RPC::accountFromString
Json::Value accountFromString(AccountID &result, std::string const &strIdent, bool bStrict)
Definition: RPCHelpers.cpp:86
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46